Parent Issue
Sub-issue of #410 (Secure Secrets Management Tool). This is Phase 2 of the phased rollout. Depends on Phase 1 (#3627).
Scope
Replace the current "pass entire os.environ to subprocesses" behavior with a tiered environment model, and add entropy-based secret detection in output.
1. Tiered environment model
| Tier |
Description |
Example |
| SAFE |
Always available to subprocesses |
PATH, HOME, USER, LANG, TERM, SHELL, TMPDIR, XDG_* |
| TOOL-MANAGED |
Available only when a tool declares it needs them via injects_env in tool registration |
FIRECRAWL_API_KEY for web_tools, BROWSERBASE_* for browser_tool |
| USER-REQUESTED |
Available only when the agent explicitly calls secrets(action="inject") before a terminal command |
TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN |
2. Terminal tool env_keys parameter
New optional parameter on the terminal tool:
terminal(
command="curl -X POST https://api.twilio.com/... -u $TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN",
env_keys=["TWILIO_ACCOUNT_SID", "TWILIO_AUTH_TOKEN"]
)
The terminal tool:
- Starts with only SAFE tier env vars
- Adds only the explicitly listed
env_keys from the secret store
- Shell
$VAR expansion works normally inside the command
- Output is redacted via
redact_sensitive_text() as usual
- Actual secret values never appear in tool call arguments or response
This extends the pattern already used by tools/mcp_tool.py (_SAFE_ENV_KEYS) to the terminal tool.
3. Tool registry injects_env field
Tool registration gains an optional injects_env field declaring which env vars the tool needs:
registry.register(
name="web_search",
toolset="web",
injects_env=["FIRECRAWL_API_KEY"],
...
)
These are automatically available when that tool's subprocess runs, without the agent needing to call secrets(action="inject").
4. Shannon entropy-based secret detection
Inspired by PII-Shield:
- Detect high-entropy strings in tool output that may be leaked secrets
- Use Shannon entropy + bigram analysis (not just regex) to catch novel key formats
- Deterministic HMAC redaction:
[HIDDEN:8f2a1b] preserves referential integrity for debugging
- Configurable threshold to balance false positives vs coverage
5. Migration path
The transition from "pass everything" to "pass only safe vars" is a breaking change for existing users whose commands depend on env vars being available. Proposed approach:
- Opt-in period: Add
terminal.env_mode: legacy (default) vs terminal.env_mode: scoped in config.yaml
- Warning mode: When
legacy, log a warning if a subprocess accesses an env var that wouldn't be available in scoped mode
- Future default: After one release cycle, switch default to
scoped
Files to Create/Modify
- Modify:
tools/terminal_tool.py — env_keys parameter, SAFE_ENV filtering
- Modify:
tools/environments/local.py — tiered env filtering (currently passes all os.environ)
- Modify:
tools/environments/*.py — apply same tiering to Docker, SSH, Modal, Daytona, Singularity backends
- Modify:
tools/registry.py — injects_env field on tool registration
- Modify:
agent/redact.py — entropy-based detection
- Modify:
hermes_cli/config.py — terminal.env_mode config key
Acceptance Criteria
References
Parent Issue
Sub-issue of #410 (Secure Secrets Management Tool). This is Phase 2 of the phased rollout. Depends on Phase 1 (#3627).
Scope
Replace the current "pass entire
os.environto subprocesses" behavior with a tiered environment model, and add entropy-based secret detection in output.1. Tiered environment model
PATH,HOME,USER,LANG,TERM,SHELL,TMPDIR,XDG_*injects_envin tool registrationFIRECRAWL_API_KEYforweb_tools,BROWSERBASE_*forbrowser_toolsecrets(action="inject")before a terminal commandTWILIO_ACCOUNT_SID,TWILIO_AUTH_TOKEN2. Terminal tool
env_keysparameterNew optional parameter on the terminal tool:
The terminal tool:
env_keysfrom the secret store$VARexpansion works normally inside the commandredact_sensitive_text()as usualThis extends the pattern already used by
tools/mcp_tool.py(_SAFE_ENV_KEYS) to the terminal tool.3. Tool registry
injects_envfieldTool registration gains an optional
injects_envfield declaring which env vars the tool needs:These are automatically available when that tool's subprocess runs, without the agent needing to call
secrets(action="inject").4. Shannon entropy-based secret detection
Inspired by PII-Shield:
[HIDDEN:8f2a1b]preserves referential integrity for debugging5. Migration path
The transition from "pass everything" to "pass only safe vars" is a breaking change for existing users whose commands depend on env vars being available. Proposed approach:
terminal.env_mode: legacy(default) vsterminal.env_mode: scopedin config.yamllegacy, log a warning if a subprocess accesses an env var that wouldn't be available inscopedmodescopedFiles to Create/Modify
tools/terminal_tool.py—env_keysparameter, SAFE_ENV filteringtools/environments/local.py— tiered env filtering (currently passes allos.environ)tools/environments/*.py— apply same tiering to Docker, SSH, Modal, Daytona, Singularity backendstools/registry.py—injects_envfield on tool registrationagent/redact.py— entropy-based detectionhermes_cli/config.py—terminal.env_modeconfig keyAcceptance Criteria
env_keysparameter works on terminal toolinjects_envon tool registration automatically scopes env vars for that toolterminal.env_modeconfig key withlegacy/scopedoptionsReferences
tools/mcp_tool.py_SAFE_ENV_KEYS— existing pattern we're extending