Skip to content

Security Audit: 4 Critical, 9 High severity findings in default configuration #7826

@Anic888

Description

@Anic888

Independent Security Audit Report

I ran a comprehensive security audit on the hermes-agent codebase (v0.8.0, 812 Python files, ~364K lines) before deciding whether to install it. Sharing the findings here so other users can make informed decisions.

TL;DR: No malware or data exfiltration found. The code is well-intentioned. But the default security posture is ALLOW-ALL, which creates real risks for users who don't know to harden it.


Methodology

Three parallel audits covering:

  1. Supply chain — dependencies, lockfiles, Dockerfile
  2. Data exfiltration & secrets — telemetry, external URLs, API key handling
  3. Shell execution & code execution — sandbox analysis, file access, skills system

Good News First

  • No malware, backdoors, or data exfiltration found
  • No telemetry or phone-home behavior — all external URLs are user-configured LLM endpoints or documented features
  • API keys sent only to intended providers — verified across the entire codebase
  • Comprehensive log redaction — 30+ API key patterns masked via RedactingFormatter
  • SSRF protection — blocks private IPs, cloud metadata endpoints
  • File permissions — config files properly set to 0o600
  • Credential stripping — local environment strips ~60+ env vars from subprocess
  • uv.lock with SHA-256 hashes — strong supply chain protection when used correctly
  • Skills guard — ~80 regex threat patterns (exfiltration, injection, destructive ops, persistence, reverse shells, crypto mining)

Critical Findings (4)

C1: Unrestricted shell command execution (local backend)

  • File: tools/environments/local.py:254-276, tools/terminal_tool.py:1133
  • The terminal tool passes arbitrary commands to bash -c via subprocess.Popen. The LLM can execute ANY shell command on the host when env_type="local" (the default).
  • Dangerous command detection is regex-based and bypassable.

C2: Full filesystem read access with no deny list

  • File: tools/file_tools.py:62-91
  • The read_file tool can read any file on the filesystem. No read deny list exists — the agent can read /etc/passwd, SSH keys, .env files, etc. The redact_sensitive_text function is applied to output only, not as access control.

C3: Approval bypass for containerized environments

  • File: tools/approval.py:591-592
  • When env_type is docker/singularity/modal/daytona, ALL approval checks are unconditionally skipped: return {"approved": True, "message": None}.

C4: LLM can create and execute persistent skills without sandbox

  • File: tools/skill_manager_tool.py:1-33
  • The agent can create skills (SKILL.md files) to ~/.hermes/skills/ that are loaded in future sessions. These become persistent prompt injection vectors. The skills guard is regex-only and agent-created skills get "ask" verdict instead of "block" for dangerous findings.

High Findings (9)

# Finding File
H1 YOLO mode (HERMES_YOLO_MODE=1) disables ALL security checks tools/approval.py:596-597
H2 Smart approval: LLM auto-approves commands via auxiliary LLM (prompt-injectable) tools/approval.py:756-767
H3 File write deny list bypassable via terminal tool (echo "..." > ~/.ssh/authorized_keys) tools/file_operations.py:45-79
H4 HERMES_WRITE_SAFE_ROOT is opt-in, not default — wide-open filesystem by default tools/file_operations.py:82-96
H5 Gateway hooks execute arbitrary Python from ~/.hermes/hooks/ gateway/hooks.py:107-115
H6 Plugin system loads arbitrary code via importlib with no sandboxing hermes_cli/plugins.py:448-494
H7 execute_code tool runs Python as regular subprocess — not a true sandbox tools/code_execution_tool.py:1-70
H8 Skills guard is regex-only static analysis — fundamentally bypassable tools/skills_guard.py:82-448
H9 3 git dependencies without commit pinning ([rl]/[yc-bench] extras) pyproject.toml

Medium Findings (9)

# Finding File
M1 Non-interactive mode auto-approves ALL commands tools/approval.py:608-611
M2 Multiple shell=True subprocess calls cli.py:5134, hermes_cli/memory_setup.py:207
M3 Reads ~/.claude/.credentials.json (Claude Code OAuth tokens) agent/anthropic_adapter.py:301-342
M4 API keys stored in plaintext (no encryption at rest) hermes_cli/config.py:156-157
M5 requirements.txt has zero version pinning requirements.txt
M6 Dockerfile: npm install --no-audit suppresses vulnerability warnings Dockerfile
M7 Dockerfile: --break-system-packages mixes system and app packages Dockerfile
M8 Tirith security scanner defaults to fail-open tools/tirith_security.py:74
M9 SSH auto-accepts new host keys (StrictHostKeyChecking=accept-new) tools/environments/ssh.py:64

Recommendations

For Users

  1. Never install on a machine with sensitive keys/wallets — use Docker or a dedicated VPS
  2. Set HERMES_WRITE_SAFE_ROOT to sandbox file writes
  3. Use Docker/Modal backend instead of local
  4. Never enable YOLO mode
  5. Set tirith_fail_open: false
  6. Install via uv pip install -e "." with uv.lock — never via requirements.txt
  7. Install only needed extras — not [all]

For Maintainers

  1. Consider making HERMES_WRITE_SAFE_ROOT opt-out instead of opt-in
  2. Add a read deny list to file_tools.py matching the existing write deny list
  3. Consider blocking terminal tool from writing to paths on the write deny list
  4. Change tirith default to fail_open: false
  5. Pin git dependencies in [rl]/[yc-bench] extras to specific commits
  6. Add version pins to requirements.txt or remove it with a note to use uv.lock
  7. Consider AST-based analysis for skills guard instead of regex-only

Audit performed using parallel static analysis agents across all 812 Python files.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existscomp/agentCore agent loop, run_agent.py, prompt buildertool/fileFile tools (read, write, patch, search)tool/terminalTerminal execution and process managementtype/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