Problem or Use Case
Summary
When a chat request to a provider fails, Hermes writes a JSON dump of
the entire outgoing request to
~/.hermes/sessions/request_dump_<session>_<timestamp>.json, including
the complete Authorization: Bearer <api-key> header value in plaintext.
The project already ships and uses agent/redact.py for redaction
elsewhere (verified by grep -r redact hermes-agent/), but the dump
path bypasses it.
This is a security issue — debug dumps of failed requests contain
credentials in a hidden directory under the operator's home.
Reproduction
- Set
OPENAI_API_KEY to a valid-format but incorrect value
(e.g. revoked key)
- Send any chat message
- After the 401 from OpenAI, inspect:
ls -la ~/.hermes/sessions/request_dump_*.json
In our test, 5 dump files were created from a single failed
session, each containing the complete sk-proj-... key in the
Authorization header.
Why this matters
These files sit in a hidden directory with no visual indicator. They
are particularly likely to be exfiltrated because they exist:
- An operator preparing a bug report does:
tar -czf hermes-bug-report.tar.gz ~/.hermes/
and the archive lands in a Slack thread, GitHub issue, or zendesk
ticket — exposing the API key.
-
Anyone with backup access (rsync ~/.hermes/ → backup-server) gets
every key the operator has ever used.
-
grep -r 'sk-proj-' ~/.hermes/ returns hits in dump files even
after the operator believes they've rotated the key, because dumps
preserve the moment of failure with the old key.
These dumps are unusually high-risk because they are failed
requests — an operator is most likely to inspect, share, or upload
them when debugging.
Suggested fix
Apply agent/redact.py (or equivalent) to the dump payload before
writing.
Specifically, redact:
- Headers (case-insensitive):
Authorization, X-API-Key, apikey,
api-key, Cookie, any header matching *-API-Key or *-Token
- Values matching credential patterns:
sk-proj-[A-Za-z0-9_-]{40,} (OpenAI)
sk-ant-[A-Za-z0-9_-]{40,} (Anthropic)
AIza[A-Za-z0-9_-]{35} (Google)
xai-[A-Za-z0-9_-]{40,} (xAI)
gsk_[A-Za-z0-9_-]{40,} (Groq)
- and any matching credential entropy + length
Keep first 8 + last 4 bytes, replace middle with *** — matching
how OpenAI itself redacts in error messages, which still preserves
debug utility (you can tell which key was used) without exposing
the secret.
Even better: opt-in dumps
Currently dumps appear to write by default for any failed request.
Consider gating behind HERMES_DUMP_FAILED_REQUESTS=1 (default off).
Operators who need them enable explicitly. This also removes the
ambient "files I didn't ask for are growing in my home dir"
surprise.
Environment
- Hermes 0.12.0 (
hermes-agent commit f903ceec)
- Python 3.11.15
- 5 dump files generated from a single 4-message failed chat session
Proposed Solution
Alternatives Considered
No response
Feature Type
New tool
Scope
None
Contribution
Debug Report (optional)
Problem or Use Case
Summary
When a chat request to a provider fails, Hermes writes a JSON dump of
the entire outgoing request to
~/.hermes/sessions/request_dump_<session>_<timestamp>.json, includingthe complete
Authorization: Bearer <api-key>header value in plaintext.The project already ships and uses
agent/redact.pyfor redactionelsewhere (verified by
grep -r redact hermes-agent/), but the dumppath bypasses it.
This is a
securityissue — debug dumps of failed requests containcredentials in a hidden directory under the operator's home.
Reproduction
OPENAI_API_KEYto a valid-format but incorrect value(e.g. revoked key)
In our test, 5 dump files were created from a single failed
session, each containing the complete
sk-proj-...key in theAuthorizationheader.Why this matters
These files sit in a hidden directory with no visual indicator. They
are particularly likely to be exfiltrated because they exist:
tar -czf hermes-bug-report.tar.gz ~/.hermes/and the archive lands in a Slack thread, GitHub issue, or zendesk
ticket — exposing the API key.
Anyone with backup access (
rsync ~/.hermes/ → backup-server) getsevery key the operator has ever used.
grep -r 'sk-proj-' ~/.hermes/returns hits in dump files evenafter the operator believes they've rotated the key, because dumps
preserve the moment of failure with the old key.
These dumps are unusually high-risk because they are failed
requests — an operator is most likely to inspect, share, or upload
them when debugging.
Suggested fix
Apply
agent/redact.py(or equivalent) to the dump payload beforewriting.
Specifically, redact:
Authorization,X-API-Key,apikey,api-key,Cookie, any header matching*-API-Keyor*-Tokensk-proj-[A-Za-z0-9_-]{40,}(OpenAI)sk-ant-[A-Za-z0-9_-]{40,}(Anthropic)AIza[A-Za-z0-9_-]{35}(Google)xai-[A-Za-z0-9_-]{40,}(xAI)gsk_[A-Za-z0-9_-]{40,}(Groq)Keep first 8 + last 4 bytes, replace middle with
***— matchinghow OpenAI itself redacts in error messages, which still preserves
debug utility (you can tell which key was used) without exposing
the secret.
Even better: opt-in dumps
Currently dumps appear to write by default for any failed request.
Consider gating behind
HERMES_DUMP_FAILED_REQUESTS=1(default off).Operators who need them enable explicitly. This also removes the
ambient "files I didn't ask for are growing in my home dir"
surprise.
Environment
hermes-agentcommitf903ceec)Proposed Solution
Alternatives Considered
No response
Feature Type
New tool
Scope
None
Contribution
Debug Report (optional)