You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hermes Agent has an inconsistent secret redaction gap: terminal output is redacted via redact_sensitive_text() in terminal_tool.py (line 1042), but file tool output is not redacted at all. This means secrets that would be masked when using cat ~/.hermes/.env via terminal are fully exposed in plain text when using read_file("~/.hermes/.env").
This was discovered while researching agent-vault, a secret-aware file I/O layer for AI agents. Testing confirmed the gap: a file with 6 different secret types was fully exposed via read_file, while terminal cat at least masked 2 of them (OpenAI and GitHub tokens).
Additionally, our current redact_sensitive_text() is purely pattern-based and only catches secrets with known prefixes (sk-, ghp_, etc.). It misses Stripe keys (sk_live_/sk_test_), AWS access keys (AKIA...), database passwords, and other high-entropy credentials. Agent-vault's entropy-based detection with bigram false-positive prevention catches all of these.
Research Findings
The Gap Demonstrated
# Via terminal (redacted by terminal_tool.py):
$ cat config.yaml
openai_key: sk-pro...x234 # ✓ masked
github_token: ghp_AB...ef12 # ✓ masked
stripe_key: sk_live_51H3kJ9dUdOoXyz123456789abc # ✗ NOT masked
aws_access_key: AKIAIOSFODNN7EXAMPLE # ✗ NOT masked
password: SuperSecretPass123!@# # ✗ NOT masked
# Via read_file (NO redaction):
openai_key: sk-proj-abc123def456ghi789jkl... # ✗ FULLY EXPOSED
github_token: ghp_ABCDEFGHIJKLMNOPQR... # ✗ FULLY EXPOSED
stripe_key: sk_live_51H3kJ9dUdOo... # ✗ FULLY EXPOSED
aws_access_key: AKIAIOSFODNN7EXAMPLE # ✗ FULLY EXPOSED
password: SuperSecretPass123!@# # ✗ FULLY EXPOSED
# Via agent-vault read (all secrets caught):
openai_key: <agent-vault:UNVAULTED:sha256:9f10ec24> # ✓ all redacted
stripe_key: <agent-vault:UNVAULTED:sha256:73a9fa45> # ✓ including unknowns
password: <agent-vault:UNVAULTED:sha256:645c8ba7> # ✓ via entropy detection
Where Redaction Is Currently Applied
Component
Redacted?
How
terminal_tool.py (line 1042)
✅ Yes
redact_sensitive_text(output)
Log files (RedactingFormatter)
✅ Yes
RedactingFormatter in run_agent.py + gateway/run.py
code_execution_tool.py
✅ Yes
Strips env vars from child process (prevention)
read_file
❌ No
Raw content returned directly
search_files (content mode)
❌ No
Matching lines returned unredacted
patch tool (diff output)
❌ No
Diffs may contain old secret values
write_file
N/A
Write deny-list blocks sensitive paths
How agent-vault's Detection Works (Inspiration)
Agent-vault uses a 3-layer detection system that catches far more secrets:
Known Pattern Matching — Similar to our _PREFIX_PATTERNS but includes Stripe, AWS AKIA, JWT (eyJ...), private key blocks, long hex/base64
Shannon Entropy Analysis — Computes character entropy; threshold of 3.0 for strings ≥12 chars catches unknown high-entropy credentials
Bigram False-Positive Prevention — Checks if a high-entropy string is actually English text using common bigram frequency (≥30% hit rate = "word-like" = not a secret). Prevents masking words like "moonshot" or "development"
Current State in Hermes Agent
agent/redact.py (115 lines) provides redact_sensitive_text() with these patterns:
Generic high-entropy strings (passwords, random tokens without known prefixes)
Implementation Plan
Skill vs. Tool Classification
This is a core codebase change, not a skill or tool. It fixes an inconsistency in existing security behavior — the redaction infrastructure exists but is not applied uniformly.
Phased Rollout
Phase 1: Apply Existing Redaction to File Tools (minimal change, high impact)
Add redact_sensitive_text() calls to file tool outputs:
tools/file_tools.py → read_file_tool(): redact result.content before returning
Overview
Hermes Agent has an inconsistent secret redaction gap: terminal output is redacted via
redact_sensitive_text()interminal_tool.py(line 1042), but file tool output is not redacted at all. This means secrets that would be masked when usingcat ~/.hermes/.envvia terminal are fully exposed in plain text when usingread_file("~/.hermes/.env").This was discovered while researching agent-vault, a secret-aware file I/O layer for AI agents. Testing confirmed the gap: a file with 6 different secret types was fully exposed via
read_file, while terminalcatat least masked 2 of them (OpenAI and GitHub tokens).Additionally, our current
redact_sensitive_text()is purely pattern-based and only catches secrets with known prefixes (sk-, ghp_, etc.). It misses Stripe keys (sk_live_/sk_test_), AWS access keys (AKIA...), database passwords, and other high-entropy credentials. Agent-vault's entropy-based detection with bigram false-positive prevention catches all of these.Research Findings
The Gap Demonstrated
Where Redaction Is Currently Applied
terminal_tool.py(line 1042)redact_sensitive_text(output)RedactingFormatterin run_agent.py + gateway/run.pycode_execution_tool.pyread_filesearch_files(content mode)patchtool (diff output)write_fileHow agent-vault's Detection Works (Inspiration)
Agent-vault uses a 3-layer detection system that catches far more secrets:
_PREFIX_PATTERNSbut includes Stripe, AWS AKIA, JWT (eyJ...), private key blocks, long hex/base64Current State in Hermes Agent
agent/redact.py(115 lines) providesredact_sensitive_text()with these patterns:sk-,ghp_,github_pat_,xox[baprs]-,AIza,pplx-,fal_,fc-,bb_live_,gAAAAOPENAI_API_KEY=value"apiKey": "value"Authorization: Bearer <token>Missing patterns (not detected):
sk_live_,sk_test_,pk_live_,pk_test_AKIA[A-Z0-9]{16}eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+-----BEGIN.*PRIVATE KEY-----Implementation Plan
Skill vs. Tool Classification
This is a core codebase change, not a skill or tool. It fixes an inconsistency in existing security behavior — the redaction infrastructure exists but is not applied uniformly.
Phased Rollout
Phase 1: Apply Existing Redaction to File Tools (minimal change, high impact)
Add
redact_sensitive_text()calls to file tool outputs:tools/file_tools.py→read_file_tool(): redactresult.contentbefore returningtools/file_tools.py→search_tool(): redact content matchestools/file_tools.py→patch_tool(): redact diff outputredact_file_output: true/false(default true) for users who want to opt outInsertion point (read_file_tool, ~line 127-128):
Phase 2: Upgrade Detection with Entropy Analysis
Enhance
agent/redact.pywith agent-vault-inspired entropy detection:Phase 3: Configurable Redaction Profiles
*.env, never redact*.py).hermesignoreor similarPros & Cons
Pros
Cons / Risks
Open Questions
[REDACTED:sk-***]or just the masked version likesk-pro...x234?References
agent/redact.py— Existing pattern-based redactiontools/terminal_tool.py:1042— Where terminal output is currently redacted