Skip to content

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

  1. User authorization: who can talk to the agent (gateway allowlists, DM pairing).
  2. Dangerous command approval: human-in-the-loop before destructive shell commands.
  3. Container isolation: Docker/Daytona/Modal as a hard boundary.
  4. MCP credential filtering: secrets stripped from MCP subprocess environments.
  5. Context file scanning: prompt-injection detection in AGENTS.md and friends.
  6. Cross-session isolation: sessions can't read each other's state.
  7. 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
ModeBehavior
manual (default)Always prompt on dangerous commands
smartAn auxiliary model assesses risk: clearly safe auto-approved, clearly dangerous auto-denied, uncertain cases prompt
offNo 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 container

Containers 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.

BackendIsolationApproval check
localNone (runs on host)Yes
sshRemote machineYes
docker / singularity / modal / daytonaContainer/cloud sandboxSkipped (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-platform

Never 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 123456789

Secrets handling

  • execute_code and terminal strip environment variables whose names contain KEY, TOKEN, SECRET, PASSWORD, etc. Allowlist specific vars with terminal.env_passthrough, or let a skill declare required_environment_variables.
  • MCP subprocesses get a filtered environment, only safe system vars plus what you explicitly set in the server's env block. Error messages from MCP tools are redacted (ghp_..., sk-..., bearer tokens).
  • Keep ~/.hermes/.env locked 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:

  1. Explicit allowlists, never allow-all.
  2. Container backend (terminal.backend: docker).
  3. chmod 600 ~/.hermes/.env and keep keys out of version control.
  4. Set an explicit terminal.cwd, don't run from a sensitive directory.
  5. Run as a non-root user.
  6. Run hermes update regularly for security patches; check hermes doctor for supply-chain advisories.

For the exhaustive pattern list and advanced topics, see the official Security page.

Personal learning notes on Hermes Agent. Not affiliated with Nous Research. Verify against official docs.