Security¶
Threat model, sandboxing strategy, and hardening guidance for Hermes Agent.
Security Track Record¶
As of April 2026, Hermes Agent has zero agent-specific CVEs. This contrasts sharply with OpenClaw, which accumulated 9 CVEs within 4 days of its March 2026 release. The difference is partly attributable to Hermes's smaller attack surface (fewer platform integrations, no marketplace of third-party skills with arbitrary code execution) and its container-first isolation model for code execution.
Threat Model¶
flowchart TB
subgraph External["External Attack Surface"]
GW["Gateway Channels<br>(Telegram, Discord, Slack, ...)"]
API["API Server<br>(REST endpoint)"]
WEB["Web Dashboard"]
end
subgraph Internal["Internal Attack Surface"]
PLUGIN["Plugin System<br>(arbitrary Python)"]
SKILL["Skills<br>(markdown + instructions)"]
TERM["Terminal Backends<br>(code execution)"]
KEYS["API Keys<br>(~/.hermes/.env)"]
DB["Session Database<br>(SQLite on disk)"]
EVOL["Self-Evolution<br>(prompt mutation)"]
end
GW -->|Auth: ALLOWED_USERS| AGENT[Agent Core]
API -->|Auth: API_SERVER_KEY| AGENT
WEB -->|No built-in auth| AGENT
AGENT --> PLUGIN
AGENT --> SKILL
AGENT --> TERM
AGENT --> KEYS
AGENT --> DB
AGENT --> EVOL
Attack Surfaces¶
| Surface | Risk | Mitigation |
|---|---|---|
| Gateway channels | Unauthorized messages from non-allowed users | *_ALLOWED_USERS env var per platform |
| API server | Remote code execution via REST | API_SERVER_KEY required for non-loopback binding |
| Web dashboard | Credential exposure (reads/writes .env) |
Binds to 127.0.0.1 by default; no built-in auth |
| Plugin system | Arbitrary Python execution | User must explicitly place files in ~/.hermes/plugins/ |
| Terminal backends | Shell command injection | Dangerous command approval + container isolation |
| API keys | Credential theft from disk | File permissions (chmod 600), env-only storage |
| Session database | History exposure | Local SQLite file, inherits OS file permissions |
| Self-evolution | Skill degradation, malicious mutations | Pareto selection, test-case validation, human review |
Sandboxing¶
Docker Backend Isolation¶
When using the Docker terminal backend, Hermes applies strict security hardening to every container:
_SECURITY_ARGS = [
"--cap-drop", "ALL", # Drop ALL Linux capabilities
"--cap-add", "DAC_OVERRIDE", # Root can write to bind-mounted dirs
"--cap-add", "CHOWN", # Package managers need file ownership
"--cap-add", "FOWNER", # Package managers need file ownership
"--security-opt", "no-new-privileges", # Block privilege escalation
"--pids-limit", "256", # Limit process count
"--tmpfs", "/tmp:rw,nosuid,size=512m", # Size-limited /tmp
"--tmpfs", "/var/tmp:rw,noexec,nosuid,size=256m", # No-exec /var/tmp
"--tmpfs", "/run:rw,noexec,nosuid,size=64m", # No-exec /run
]
Key protections:
- All Linux capabilities dropped except three required for package management
- Privilege escalation explicitly blocked via
no-new-privileges - Process count capped at 256 to prevent fork bombs
- Temporary directories are size-limited and mounted with
noexec/nosuid
Singularity / Modal / Daytona Isolation¶
Container-based backends (Singularity, Modal, Daytona) provide namespace isolation from the host. Modal and Daytona run in cloud-managed sandboxes with additional provider-level isolation. For all container backends, dangerous command checks are skipped because the container itself is the security boundary.
Container image trust
The default image (nikolaik/python-nodejs:python3.11-nodejs20) is a community-maintained image. For production deployments, consider building and hosting your own images from a trusted base.
Dangerous Command Approval (Local Backend)¶
The local backend checks every command against a curated list of dangerous patterns before execution:
- Recursive deletes (
rm -rf) - SQL drops (
DROP TABLE,DROP DATABASE) - Piping curl to shell (
curl ... | bash) - Permission changes on system directories
- Other destructive patterns
When a dangerous command is detected, the agent presents an interactive approval prompt with options: [o]nce, [s]ession, [a]lways, or [d]eny.
API Key Management¶
API keys are stored in ~/.hermes/.env and managed via the CLI:
hermes config set OPENROUTER_API_KEY sk-or-... # Auto-routed to .env
hermes config set ANTHROPIC_API_KEY sk-ant-...
Best practices:
- Never commit
.envfiles to version control - Use per-profile
.envfiles (~/.hermes/profiles/<name>/.env) to isolate credentials between use cases - In Docker, pass keys via
-eflags instead of mounting.envto avoid on-disk storage - Use
env_passthroughinconfig.yamlto forward only required keys to sandboxed backends
Channel Authentication¶
Each platform adapter enforces an allowlist of authorized user IDs:
| Platform | Env Variable | Format |
|---|---|---|
| Telegram | TELEGRAM_ALLOWED_USERS |
Comma-separated numeric user IDs |
| Discord | DISCORD_ALLOWED_USERS |
Comma-separated Discord user IDs |
| Slack | SLACK_ALLOWED_USERS |
Comma-separated Slack Member IDs |
Messages from users not in the allowlist are silently dropped. There is no open-registration mode.
Memory and Session Data Protection¶
Session data is stored in local SQLite files under ~/.hermes/. Protection relies on:
- OS file permissions — SQLite files inherit the permissions of the Hermes data directory
- Per-platform session isolation — sessions from different platforms are stored separately, preventing cross-channel data leakage
- Atomic writes — contention handling prevents corruption during concurrent access
No encryption at rest
SQLite session data is not encrypted at rest. If the host is compromised, all conversation history is accessible. For sensitive environments, run Hermes in an encrypted filesystem or use a container backend with ephemeral storage.
Self-Evolution Safety¶
The DSPy + GEPA self-evolution system introduces a unique risk: autonomous modification of skills and prompts could degrade agent quality or introduce harmful behaviors.
Safeguards:
- Test-case validation — every mutated variant is evaluated against test cases before acceptance
- Pareto selection — variants must be optimal across multiple objectives (quality, cost, speed), preventing single-metric gaming
- Execution trace analysis — the GEPA optimizer reads traces to understand why failures occur, reducing blind mutations
- Human review — evolution runs produce diffs that can be reviewed before deployment
- Rollback — skills are versioned; previous versions can be restored via
hermes skills reset <name> --restore
Unattended evolution
Running self-evolution unattended in production is not recommended at v0.9.0. Review generated diffs before deploying evolved skills to production agents.
Plugin Security¶
Plugins execute arbitrary Python in the agent process with no sandboxing. Risks include:
- Data exfiltration (reading
.env, session database, filesystem) - Code injection (registering malicious tools)
- Denial of service (blocking the agent loop)
Mitigations:
- Plugins must be explicitly placed in
~/.hermes/plugins/or.hermes/plugins/by the user - Hub-installed skills are scanned on install (
hermes skills installruns a security scan) - Periodic re-scanning is available via
hermes skills audit - There is no runtime sandbox for plugins -- trust is placement-based
Network Security¶
API Server Binding¶
The API server gives full access to Hermes's toolset, including terminal commands. The API_SERVER_KEY is required when binding to a non-loopback address:
# Safe: loopback only (default)
hermes api --host 127.0.0.1
# Requires API_SERVER_KEY for non-loopback
hermes api --host 0.0.0.0
Keep API_SERVER_CORS_ORIGINS narrow to control browser access.
Web Dashboard¶
The web dashboard reads and writes ~/.hermes/.env. It binds to 127.0.0.1 by default.
Dashboard exposure
Binding the dashboard to 0.0.0.0 exposes your API keys and credentials to anyone on your network. The dashboard has no built-in authentication. Use a reverse proxy with TLS and authentication if remote access is required.
Gateway Network Exposure¶
Platform adapters use outbound connections (long polling, WebSocket) and do not require inbound port exposure in most configurations. Exceptions:
- Webhook mode (Telegram, Feishu, WeCom) requires an inbound HTTPS endpoint
- API server adapter requires a listening port
For webhook-based platforms, deploy behind a reverse proxy with TLS termination.