harden(env_passthrough): apply GHSA-rhgp-j443-p4rf filter to config.yaml path - #27794
Merged
teknium1 merged 1 commit intoMay 25, 2026
Merged
Conversation
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Apply the same Hermes-provider-credential filter to the config.yaml path of
tools/env_passthrough.pythat already exists on the skill-declared path.Three lines of real change; a few more for the warning message and a small
comment explaining why.
The asymmetry this closes
tools/env_passthrough.pyhas two intake paths that feed the same allowlist:register_env_passthrough()(line 70). Called when a skill declaresrequired_environment_variablesin its frontmatter. This path filtersvia
_is_hermes_provider_credential()and refuses to register any namethat is in
_HERMES_PROVIDER_ENV_BLOCKLIST, logging a warning thatcites GHSA-rhgp-j443-p4rf.
_load_config_passthrough()(line 103). Readsterminal.env_passthroughfrom
config.yaml. Does not filter at all; whatever string is in thelist goes into the allowlist as-is.
Both feed
is_env_passthrough()(line 125), which is consulted bytools/environments/local.pyandtools/code_execution_tool.pybeforethey strip a variable from the child env.
The docstring on
register_env_passthroughframes the filter as aguarantee about the
execute_codesandbox's credential scrubbing, not asa skill-specific check. The config path silently breaks that guarantee.
Why it matters
The GHSA-rhgp-j443-p4rf fix landed because a malicious skill could
register
ANTHROPIC_TOKEN/OPENAI_API_KEYas passthrough and receivethe credential in an
execute_codechild. The fix closed the skill pathbut left the config path open. Two scenarios where that gap is
reachable today:
terminal.env_passthroughinconfig.yaml"so this skill can work."The skill can't register the name itself anymore (filtered), so it
social-engineers the operator into doing it via config. The operator
sees a config-edit suggestion in plain text and might accept it, even
though the same registration via the skill's own frontmatter would be
refused.
~/.hermes/config.yaml(thepath is not in
_check_sensitive_path's blocklist intools/file_tools.py) can extend the allowlist with provider keys,bypassing the GHSA fix without going through the skill loader at all.
Neither is a "vulnerability" under the existing SECURITY.md (operator
trust envelope), and I'm not framing it that way. It's a defense-in-depth
inconsistency: the skill-path docstring promises a guarantee that the
config-path silently breaks.
The fix
Apply the same
_is_hermes_provider_credentialfilter inside_load_config_passthrough, with a warning message that mirrors theskill-path one but says "Operator configuration" and "config.yaml"
instead of "Skills".
Behavior changes
terminal.env_passthroughfor non-Hermes API keys(
TENOR_API_KEY,NOTION_TOKEN, etc.): no change. Those names aren'tin
_HERMES_PROVIDER_ENV_BLOCKLIST, so they pass through as before.terminal.env_passthroughforANTHROPIC_API_KEY(or any other Hermes-managed provider key): the entry is ignored at
load time, with a
logger.warningthat explains why. Theexecute_code/ terminal sandboxes see the variable scrubbed, asintended by GHSA-rhgp-j443-p4rf.
If an operator has a legitimate reason to expose a Hermes-managed
provider key to an
execute_codechild (for example, a test script thatcalls the same provider), I'd be happy to add a separate explicit
terminal.env_passthrough_unsafeknob in a follow-up that takes thefilter off, so the choice is loud and named. Wanted to keep this PR
surgical.
Context
I found this while doing a private security review of hermes-agent
v2026.5.16 ahead of upstreaming a few fixes for Fox in the Box. The
review followed the SECURITY.md scope rules and didn't surface anything
that's an advisory-grade vulnerability, so this is the cleanest "good
citizen" hardening item it produced. Filing it as a regular PR rather
than a private advisory, per the SECURITY.md guidance for in-process
heuristic improvements.
Happy to add a regression test if you want one. The natural home looks
like
tests/tools/test_env_passthrough_config_filter.py, covering:(1) a benign third-party key in
terminal.env_passthroughpassesthrough; (2) a name from
_HERMES_PROVIDER_ENV_BLOCKLISTinterminal.env_passthroughis rejected with a logger.warning;(3)
is_env_passthrough()returns False for the rejected name evenwhen it appears verbatim in config.