← All writing.md

How Hermes Agent thinks about security: eight layers, one real boundary

October 25, 2026 · 12 min read

Every AI agent that can run a shell command carries a basic question: what actually stops it from doing something destructive, whether by accident or because someone fed it a malicious instruction from a web page or document. The same question applies to an agent that writes files or browses the web on your behalf. Most agent frameworks answer with a pile of safety checks layered onto the model and leave it at that.

Hermes Agent, the open source agent framework from Nous Research, writes a more honest version of the answer straight into its own security policy. It lists eight layers of defense, and then says plainly that most of them are not boundaries at all. They are speed bumps for a cooperative model that makes an honest mistake, not a cage for a hostile one. The one thing that actually holds against a hostile model sits below the agent entirely.

That split, eight layers of heuristics on top of one real boundary, is worth understanding whether you run Hermes Agent, build your own agent, or just want to know how much to trust the one your company already runs.

What are the eight layers?

Hermes Agent's documentation names them directly:

Diagram of Hermes Agent's eight security layers stacked around the one real boundary, OS-level isolation
The eight layers, and the one boundary they all sit on top of
  • User authorization, layered allowlists that decide who can even talk to the agent on a messaging platform.
  • Dangerous command approval, a human-in-the-loop check before destructive shell commands run.
  • File write safety, a denylist (plus an optional write sandbox) for every file the agent tries to create or edit.
  • Container isolation, hardened Docker and cloud sandbox settings for running commands.
  • MCP credential filtering, stripping most environment variables and secrets before they reach a subprocess or a connected tool server.
  • Context file scanning, checking project files like AGENTS.md for hidden prompt injection before they enter the system prompt.
  • Cross-session isolation, keeping one conversation's data and approvals away from another's, with path-traversal hardening on where scheduled jobs store their state.
  • Input sanitization, validating parameters like a terminal's working directory against an allowlist so they cannot be used to smuggle in a shell command.

Each one catches a real class of mistake. None of them, on its own or together, is a wall against a model that is actively trying to get around them.

Hermes Agent's public Security documentation page, showing the eight-layer defense-in-depth overview
Hermes Agent's Security docs: the eight-layer overview (hermes-agent.nousresearch.com)

Who is allowed to talk to the agent?

The first layer is the simplest and the easiest to get wrong: who can even open a conversation with the agent. Hermes Agent checks a messaging platform's allowlists in order, from a per-platform allow-all flag down to a global allowlist, and if nothing is configured at all, the default is deny. An agent with no allowlist set up does not quietly accept messages from strangers; it refuses everyone and logs a warning explaining why.

For less predictable access, there is a pairing system: a first-time user who messages the bot gets a one-time code, and the bot owner approves it via CLI before that person can use the agent at all.

What happens before a dangerous command runs?

The approval system has three modes. smart mode uses a second, auxiliary model to judge risk: a harmless command like printing text runs immediately, a genuinely dangerous one is auto-denied, and anything uncertain goes to a manual prompt. manual mode always asks. off mode, equivalent to running with --yolo, skips every prompt. An operator sets the mode directly in config:

approvals:
  mode: smart
  cron_mode: deny
  unattended_mode: deny

This is where the framework gets specific about context that matters a lot in practice: cron jobs, single-shot queries, and webhook or API sessions have nobody sitting there to answer a prompt, so by default they all deny a dangerous command outright rather than silently approving it. An operator can flip that to auto-approve, but the safe default assumes no human is watching.

There is also a session-scoped "YOLO" mode that bypasses approval prompts entirely, with two deliberate, hard-to-miss visual reminders (a banner at session start and a persistent status-bar marker) so it is difficult to forget it is on. Even YOLO mode cannot bypass a fixed, code-level blocklist of catastrophic commands: recursive deletes of the filesystem root, fork bombs, formatting a mounted disk, and similar operations are refused unconditionally, with no override flag at all.

What stops it from overwriting your credentials?

Before the agent writes or edits any file, Hermes checks the target path against a hardcoded denylist of credential locations: SSH keys, AWS and Kubernetes credentials, sudoers, and the agent's own secret stores like .env files and OAuth token caches. A blocked write returns an error immediately, with no approval prompt and no way around it from the chat interface.

One detail stands out: project-local .env files are blocked from being read by the agent's file tools anywhere on disk, but they remain writable. The agent can create or edit a .env file for you, it just cannot read the values back out of it. For example, it can add a new key to .env, but if you ask it to print the file's contents, that read is blocked. That asymmetry is a deliberate design choice, not a gap: it lets the agent help you configure tools without being able to steal the keys already in place.

The documentation is explicit that this denylist is defense in depth, not a hard boundary: the terminal tool runs as the same operating system user, and a shell command can still read or overwrite a path the file-write denylist blocks. The denylist stops an accidental or cooperative mistake. It does not sandbox a hostile one.

Does a container actually contain it?

This is where Hermes Agent's model gets precise about what a container is actually for. When the agent runs commands through a non-default terminal backend such as Docker, Modal, or a cloud sandbox, the dangerous-command approval check is skipped entirely, because the container itself becomes the security boundary instead. There is no need to ask permission for a destructive command if that command cannot reach anything outside the sandbox.

The Terminal Backend Security Comparison table from Hermes Agent's docs, listing local, ssh, docker, modal, daytona and vercel_sandbox
Which terminal backends skip the dangerous-command check, and why (hermes-agent.nousresearch.com)

The local backend, by contrast, runs commands directly on the host and keeps the dangerous-command check active, because there is no container standing between the agent and the real filesystem. Choosing a backend is choosing which kind of defense you are relying on: approval prompts for a trusted but imperfect operator, or an actual sandbox boundary for untrusted input.

Docker containers that Hermes Agent spawns also get hardened by default: every Linux capability is dropped and only a few narrow ones (needed for package managers to change file ownership) are added back, privilege escalation is blocked, the process count is capped, and temporary directories are mounted with restricted sizes and no-exec flags where it matters.

What about secrets passed to subprocesses?

Any subprocess the agent spawns, whether a shell command, a code-execution sandbox, or a connected MCP (Model Context Protocol, a standard for connecting external tools to an LLM) tool server, gets a filtered environment by default. An MCP server subprocess, specifically, only receives a short list of safe variables (PATH, HOME, USER, and a few others) plus anything explicitly declared in its own configuration. API keys, tokens, and other secrets are stripped unless an operator or a skill deliberately declares them as needed.

Hermes Agent also sanitizes error messages coming back from MCP tools before sending them to the model: GitHub tokens, OpenAI-style keys, bearer tokens, and common key=/password= parameters are replaced with a redacted marker. This cuts down on casual leakage, but the documentation is careful to note the limit of what it protects: anything running inside the agent's own process, including a loaded skill or plugin, can still read whatever the agent process itself can read, including credentials already sitting in memory.

Is a skill or plugin safe to install?

Skills and plugins both load directly into the agent's own process and run with its full privileges. Hermes Agent ships a scanner, Skills Guard, that checks installable skill content for suspicious patterns before you add it. The framework is explicit that this scanner is a review aid, not a boundary: the only thing that actually protects you from a malicious skill is reading its code yourself before installing it, because a skill's Python runs the moment it is imported, not just when you invoke it.

The same logic applies to plugins, which the policy treats as more complex because they often ship their own background services and dependencies. A compromised or badly written third-party skill is not treated as a bug in Hermes Agent. It is treated as the expected outcome of installing something without reading it.

Isn't any of this a real wall?

Here is the sentence that frames the entire policy: the only security boundary against an adversarial model is the operating system. Nothing that runs inside the agent's own process counts as containment, not the approval gate, not the secret redaction, not any scanner. Every one of those is a heuristic operating on a string the model itself may have influenced, and a sufficiently motivated adversary can produce output that gets past a heuristic built to catch it.

Hermes Agent's SECURITY.md on GitHub, with the sentence naming the operating system as the only real boundary
Hermes Agent's SECURITY.md: the one sentence that frames the whole policy (github.com/NousResearch/hermes-agent)

Hermes Agent supports two ways of actually delivering that boundary. The lighter one, terminal-backend isolation, runs shell and file commands inside a container or on a remote host, which confines anything the agent does by issuing shell or file operations. It explicitly does not confine everything else the agent does in its own Python process: a code-execution tool spawned as a host subprocess, an MCP subprocess, or a skill or plugin loaded into the interpreter all sit outside that boundary.

The heavier option, whole-process wrapping, puts the entire agent process tree inside a sandbox, so every code path (shell, code execution, MCP, file tools, plugins, hooks, skill loading) answers to the same filesystem, network, and process policy. Hermes Agent's own Docker image offers a lighter version of this; a project called NVIDIA OpenShell offers a more granular one, with per-session sandboxes, hot-reloadable network and inference policy, and credentials injected from a separate store that never touches the sandbox's own filesystem. Under a whole-process wrapper, all those in-process heuristics from earlier become accident prevention layered on top of a boundary that is actually load-bearing, which is the posture the project recommends whenever the agent reads content from surfaces an operator does not fully control, such as the open web, inbound email, or multi-user chat.

Keeping it off the internet entirely

Even inside a sandbox, an operator may still want to restrict what the agent can reach on the network. That is what egress isolation adds. For Docker deployments specifically, Hermes Agent documents a network-level defense aimed at one particular attack: a prompt-injection attack that tries to get a tool-generated shell command to exfiltrate data with curl or wget. Container isolation stops the agent from breaking out of its own process to touch the host. Network isolation stops it from calling home even if a malicious instruction slips through. The default Docker setup gives the agent process unrestricted outbound access. The hardened version splits the deployment across two Docker networks.

Diagram of the two-Docker-network egress isolation topology: an internal network with no route out, and an egress network for services that need the internet
The two-network egress topology for Docker deployments

One network, called internal, has no default route and no internet access at all; the agent, the dashboard, and the gateway process run there. The other, egress, does have internet access, and only the services that actually need to reach an external API sit on it. The gateway is dual-homed across both, so it can receive an inbound message from Telegram or Slack and still hand the work to an agent that otherwise cannot reach the open internet. For tighter control, outbound traffic from the egress network can route through a proxy with an explicit allowlist of hostnames, so even a successfully injected command can only reach a small, named set of destinations rather than anywhere on the internet.

The documentation is upfront about the limits here too: a container on the internal network can usually still resolve external DNS names unless a local resolver blocks that separately, and network segmentation is not a substitute for a sandboxed terminal backend. It is one more layer, matched to one specific threat, not a replacement for the OS-level boundary described above.

Taken together, the shape of Hermes Agent's security model is less about any single clever check and more about naming, in public, exactly which of its defenses are real and which are not. The eight layers catch honest mistakes and slow down a casual attacker. The operating system, via a sandboxed terminal backend or a whole-process wrapper, is the only thing standing between a genuinely adversarial model and the rest of your machine. Anyone deploying an agent, Hermes Agent or otherwise, is better off starting from that same question: if the model itself turned hostile, what below it would actually stop it.

What to take away: Hermes Agent's safety checks prevent accidents, not adversarial attacks. That job belongs to the operating system underneath, through a sandboxed terminal backend or a whole-process wrapper. Read its security documentation and its SECURITY.md in full before deciding how to deploy one.

Follow along at https://x.com/myargoquest, and the project itself is open source at https://github.com/NousResearch/hermes-agent.

Start your 750 words today

Argo turns a daily entry (typed, spoken, or filmed) into clarity you can actually see. Private, encrypted, and built entirely from your own life.

Download on the App Store