Skip to content

[Feature]: request_dump_*.json files in ~/.hermes/sessions/ contain plaintext Authorization headers — agent/redact.py exists but isn't applied on this path #18707

@vtbjbb-alt

Description

@vtbjbb-alt

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

  1. Set OPENAI_API_KEY to a valid-format but incorrect value
    (e.g. revoked key)
  2. Send any chat message
  3. 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

  • I'd like to implement this myself and submit a PR

Debug Report (optional)

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High — major feature broken, no workaroundcomp/agentCore agent loop, run_agent.py, prompt buildersweeper:implemented-on-mainSweeper: behavior already present on current maintype/securitySecurity vulnerability or hardening

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions