Skip to content

Security: write_file/patch can modify ~/.hermes control-plane files (auth.json, config.yaml, webhook subscriptions) #14072

@alsaif

Description

@alsaif

Summary

write_file and patch block a handful of sensitive paths, but the deny list does not cover Hermes control-plane files under HERMES_HOME such as ~/.hermes/auth.json, ~/.hermes/config.yaml, and ~/.hermes/webhook_subscriptions.json.

Because these tools are available without going through terminal approval, a prompt-injected model can persistently modify Hermes runtime/auth/configuration state directly through the file tools.

Affected code

  • tools/file_operations.py:45-79 — static write deny list only covers .ssh, .aws, shell rc files, .env, etc.
  • tools/file_operations.py:683-685write_file denies only _is_write_denied(path).
  • tools/file_operations.py:740-742patch_replace uses the same deny list.
  • tools/file_tools.py:541-556write_file_tool() relies on the same checks.
  • tools/file_tools.py:565-600patch_tool() relies on the same checks.

Impact

A malicious prompt, compromised MCP/tool output, or indirect prompt injection can use file tools to silently modify Hermes trust-boundary files without triggering dangerous-command approval. Examples:

  • overwrite ~/.hermes/config.yaml to change providers, routing, startup behavior, or enabled features
  • modify ~/.hermes/auth.json / OAuth state to break or redirect future auth flows
  • alter ~/.hermes/webhook_subscriptions.json to persist attacker-controlled webhook behavior
  • tamper with other profile control files under HERMES_HOME

This creates a persistence/backdoor path that survives the current session and affects future runs.

Why this is distinct from generic "wide-open filesystem" concerns

The problem is not just that writes are broad by default — it is that Hermes' own security-sensitive control-plane files are not treated as protected, even though they directly govern future agent behavior and credentials.

Suggested fix

Treat Hermes control-plane files as protected by default in _is_write_denied().

At minimum block writes/patches to:

  • get_hermes_home() / "auth.json"
  • get_hermes_home() / "config.yaml"
  • get_hermes_home() / ".env" (already blocked; keep it)
  • get_hermes_home() / "webhook_subscriptions.json"
  • get_hermes_home() / "mcp-tokens"/**
  • Hermes hook/plugin registry paths and any executable hook directories

A stronger long-term fix would be to make file writes workspace-scoped by default and require explicit approval for writes under HERMES_HOME.

Severity

High — persistent agent reconfiguration / future-session compromise via prompt-driven file writes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0Critical — data loss, security, crash looparea/authAuthentication, OAuth, credential poolsarea/configConfig system, migrations, profilescomp/toolsTool registry, model_tools, toolsetstool/fileFile tools (read, write, patch, search)type/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