Appearance
Security model
An autonomous agent with terminal access is powerful and, if you're careless, dangerous. Hermes is built with defense-in-depth: several independent layers that each catch a different class of risk. This page is the map of those layers and the knobs you actually turn.
The layers
- User authorization: who can talk to the agent (gateway allowlists, DM pairing).
- Dangerous command approval: human-in-the-loop before destructive shell commands.
- Container isolation: Docker/Daytona/Modal as a hard boundary.
- MCP credential filtering: secrets stripped from MCP subprocess environments.
- Context file scanning: prompt-injection detection in AGENTS.md and friends.
- Cross-session isolation: sessions can't read each other's state.
- Input sanitization: working-directory and command inputs validated.
Command approval
Before running a command, Hermes checks it against a curated list of dangerous patterns (recursive deletes, mkfs, dd, SQL DROP/DELETE, piping curl to a shell, writes to /etc or ~/.ssh, and more). On a match, you are asked to approve.
yaml
# ~/.hermes/config.yaml
approvals:
mode: manual # manual | smart | off
timeout: 60 # seconds to wait before denying (fail-closed)
cron_mode: deny # how cron jobs behave on a dangerous command| Mode | Behavior |
|---|---|
manual (default) | Always prompt on dangerous commands |
smart | An auxiliary model assesses risk: clearly safe auto-approved, clearly dangerous auto-denied, uncertain cases prompt |
off | No prompts (same as --yolo) |
In the CLI, a prompt offers once / session / always / deny. Commands approved with "always" are saved to command_allowlist in config.yaml, review it occasionally with hermes config edit.
The hardline blocklist (always on)
A few commands are so catastrophic, rm -rf /, fork bombs, formatting a mounted root device, zeroing a disk, that Hermes refuses them regardless of --yolo, approvals.mode: off, or an "always" allow. There is no override flag. This is the floor below YOLO mode.
YOLO mode
hermes --yolo or /yolo bypasses all approval prompts for the session (except the hardline blocklist). Use it only in disposable, trusted environments. A red banner and status-bar marker remind you while it's active.
Container isolation is the strongest boundary
A profile is not a sandbox, on the default local backend the agent has your full user permissions. For real isolation, run a container backend:
yaml
# ~/.hermes/config.yaml
terminal:
backend: docker
docker_image: "nikolaik/python-nodejs:python3.11-nodejs20"
container_memory: 5120
docker_forward_env: [] # empty keeps host secrets out of the containerContainers run hardened (all Linux capabilities dropped, no-new-privileges, pid limits, size-limited tmpfs). Inside a container, dangerous-command approval is skipped, because the container itself is the boundary; destructive commands can't reach the host.
| Backend | Isolation | Approval check |
|---|---|---|
local | None (runs on host) | Yes |
ssh | Remote machine | Yes |
docker / singularity / modal / daytona | Container/cloud sandbox | Skipped (container is the boundary) |
Gateway authorization
If you expose the agent on a messaging platform, control who can use it. The default is deny: with no allowlists configured, all users are rejected.
bash
# ~/.hermes/.env
TELEGRAM_ALLOWED_USERS=123456789,987654321
DISCORD_ALLOWED_USERS=111222333444555666
GATEWAY_ALLOWED_USERS=123456789 # cross-platformNever set GATEWAY_ALLOW_ALL_USERS=true on a bot with terminal access. For convenience, DM pairing lets an unknown user receive a one-time code that you approve:
bash
hermes pairing list
hermes pairing approve telegram ABC12DEF
hermes pairing revoke telegram 123456789Secrets handling
execute_codeandterminalstrip environment variables whose names containKEY,TOKEN,SECRET,PASSWORD, etc. Allowlist specific vars withterminal.env_passthrough, or let a skill declarerequired_environment_variables.- MCP subprocesses get a filtered environment, only safe system vars plus what you explicitly set in the server's
envblock. Error messages from MCP tools are redacted (ghp_...,sk-..., bearer tokens). - Keep
~/.hermes/.envlocked down:chmod 600 ~/.hermes/.env.
Web access controls
- SSRF protection is always on for URL tools: private networks, loopback, link-local, and cloud-metadata addresses are blocked by default. To allow LAN/localhost access (a local wiki, an internal endpoint), set
security.allow_private_urls: true, a deliberate trust boundary. - Website blocklist: restrict which domains the agent may reach via
security.website_blocklist.
Production gateway checklist
If you run an always-on gateway, the essentials:
- Explicit allowlists, never allow-all.
- Container backend (
terminal.backend: docker). chmod 600 ~/.hermes/.envand keep keys out of version control.- Set an explicit
terminal.cwd, don't run from a sensitive directory. - Run as a non-root user.
- Run
hermes updateregularly for security patches; checkhermes doctorfor supply-chain advisories.
For the exhaustive pattern list and advanced topics, see the official Security page.