From 8618eba7c8dc0d57ef9669a7a3f428cd7a33cb90 Mon Sep 17 00:00:00 2001 From: witcheer <208820874+notwitcheer@users.noreply.github.com> Date: Wed, 5 Aug 2026 06:53:15 +0000 Subject: [PATCH] docs: add security-posture guide for running Hermes on a personal or work machine --- .../guides/secure-hermes-on-a-work-machine.md | 182 ++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 website/docs/guides/secure-hermes-on-a-work-machine.md diff --git a/website/docs/guides/secure-hermes-on-a-work-machine.md b/website/docs/guides/secure-hermes-on-a-work-machine.md new file mode 100644 index 0000000000000..280f26b4bd095 --- /dev/null +++ b/website/docs/guides/secure-hermes-on-a-work-machine.md @@ -0,0 +1,182 @@ +--- +sidebar_position: 26 +title: "Running Hermes on a Personal or Work Machine" +description: "A security-posture walkthrough for running Hermes Agent on the machine you live on — what the defaults protect, how to tighten further, and how to undo mistakes" +--- + +# Running Hermes on a Personal or Work Machine + +You're about to run an agent on the machine you live on — a personal laptop or an employer-managed workstation. What's the safe posture? + +Short answer: the defaults already do most of the work. Hermes ships secure-by-default, with a defense-in-depth model covering command approval, file-write safety, and credential handling. This page walks through what's on out of the box, which knobs to tighten for a shared or work machine, and how to undo mistakes when they happen. Every control here is covered in depth in the [Security](/user-guide/security) guide. + +## What the Defaults Already Protect + +Fresh install, no configuration — these protections are active: + +**Dangerous commands require approval.** Before executing any command, Hermes checks it against a curated list of dangerous patterns — recursive deletes, writes to `/etc/`, disk operations, pipe-to-shell, and more. The default `approvals.mode: smart` uses an auxiliary LLM to assess risk: low-risk commands are auto-approved for that command only, genuinely dangerous commands are auto-denied, and uncertain cases escalate to a manual prompt. + +**Approval prompts fail closed.** If you don't respond to an approval prompt within the timeout (default 300 seconds), the command is **denied**. Walking away from your desk never silently approves anything. + +**A hardline blocklist is the always-on floor.** Some commands — `rm -rf /`, fork bombs, zeroing a physical disk — are refused **regardless** of approval mode, `--yolo`, or an explicit "allow always". The blocklist trips before the approval layer even sees the command, and there is no override flag. + +**File writes to sensitive paths are blocked.** The `write_file` and `patch` tools cannot touch OS credential stores (`~/.ssh/`, `~/.aws/`, `~/.kube/`, `/etc/sudoers`, `~/.netrc`), Hermes credential stores (`auth.json`, `.env`, pairing data), or project secret files (`.env`, `.env.local`, `.envrc`) anywhere on disk. Blocked writes return an error immediately — there is no approval prompt and no way to override from the chat UI. + +**Secrets are redacted from output.** `security.redact_secrets` is on by default: patterns that look like API keys, tokens, and passwords in tool output are redacted before they enter the conversation context and logs. + +**Your data goes only where you point it.** API calls go **only to the LLM provider you configure**. Hermes Agent does not collect telemetry, usage data, or analytics. Your conversations, memory, and skills are stored locally in `~/.hermes/`. See the [FAQ](/reference/faq#is-my-data-sent-anywhere). + +:::info +There's more below the surface — SSRF protection on all URL-capable tools, filtered environments for MCP subprocesses, prompt-injection scanning of context files. The [Security](/user-guide/security) page documents every layer. +::: + +## Tightening for a Shared or Work Machine + +On a machine with employer data, production credentials, or other people's files, layer these on top of the defaults. + +### Switch approvals to manual + +`smart` mode auto-approves low-risk commands. If you want to see every flagged command yourself: + +```yaml +approvals: + mode: manual +``` + +Manual mode always prompts you before executing a flagged command. + +### Add your own deny rules + +`approvals.deny` is a list of glob patterns that block matching terminal commands unconditionally — even under `--yolo`, `/yolo`, or `mode: off`. It's the user-editable counterpart to the built-in hardline blocklist. Use it to declare things that must never run on this machine: + +```yaml +approvals: + deny: + - "git push --force*" + - "*curl*|*sh*" + - "dd if=* of=/dev/*" +``` + +Patterns are case-insensitive [fnmatch](https://docs.python.org/3/library/fnmatch.html) globs matched against the whole command text, and matching runs over the same normalized/deobfuscated variants the dangerous-pattern detector uses, so simple quoting tricks don't slip past a rule. Always quote patterns — a bare leading `*` is a YAML parse error. Changes take effect immediately, no restart needed. Details: [User-Defined Deny Rules](/user-guide/security#user-defined-deny-rules-approvalsdeny). + +### Sandbox file writes + +`HERMES_WRITE_SAFE_ROOT` restricts `write_file` and `patch` to the directory prefix(es) you list — anything outside is hard-blocked. Multiple roots are separated by `:` on Unix: + +```bash +export HERMES_WRITE_SAFE_ROOT=/path/to/project:/home/you/.hermes +``` + +Sensitive paths inside the safe root are still blocked — pointing it at `$HOME` does not allow writing `~/.ssh/id_rsa`. + +:::caution +Don't add this to `~/.hermes/.env` casually. If you set it to a project directory only, the agent cannot write to `~/.hermes/cron/jobs.json`, profile skills, or other Hermes state outside that prefix. Include your Hermes home as a second root, as above. +::: + +### Move command execution off the host + +The strongest isolation is not running commands on your machine at all. The terminal tool supports multiple [backends](/user-guide/features/tools#terminal-backends): + +| Backend | Isolation | +|---------|-----------| +| `local` | None — runs on host (dangerous-command checks apply) | +| `docker` | Container — the container itself is the security boundary | +| `ssh` | Remote machine — keeps execution on a separate server | + +```yaml +terminal: + backend: docker + docker_image: "nikolaik/python-nodejs:python3.11-nodejs20" + docker_forward_env: [] # Explicit allowlist only; empty keeps secrets out of the container +``` + +Every Docker container runs with hardened settings — all Linux capabilities dropped (with a minimal add-back set), `no-new-privileges`, a process-count limit, and size-limited tmpfs mounts. With a container backend, destructive commands inside the container can't harm the host, which is why dangerous-command checks are skipped there. + +For `ssh`, set `terminal.backend: ssh` in `config.yaml` and provide host details via `TERMINAL_SSH_HOST`, `TERMINAL_SSH_USER`, and `TERMINAL_SSH_KEY` in `~/.hermes/.env`. See [Network Isolation](/user-guide/security#network-isolation). + +### If messaging is on: allowlists and pairing + +Running the [gateway](/user-guide/security#user-authorization-gateway) on this machine? The default is already deny: if no allowlists are configured and `GATEWAY_ALLOW_ALL_USERS` is not set, **all users are denied**. Keep it explicit: + +```bash +# ~/.hermes/.env +TELEGRAM_ALLOWED_USERS=123456789 +GATEWAY_ALLOWED_USERS=123456789 +``` + +Or use DM pairing instead of hardcoding IDs: unknown users receive a one-time pairing code, and you approve them from the CLI with `hermes pairing approve `. Never set `GATEWAY_ALLOW_ALL_USERS=true` on a machine you care about. + +## The Undo Layer: Checkpoints and `/rollback` + +Approval gates prevent damage; [checkpoints](/user-guide/checkpoints-and-rollback) reverse it. When enabled, Hermes automatically snapshots your project before destructive operations — `write_file`, `patch`, and destructive terminal commands like `rm`, `mv`, `sed -i`, and `git reset` — into a shadow git store under `~/.hermes/checkpoints/store/`. Your real project `.git` is never touched. + +Checkpoints are opt-in. Enable per-session: + +```bash +hermes chat --checkpoints +``` + +Or globally: + +```yaml +checkpoints: + enabled: true +``` + +Then, in a session: + +| Command | Description | +|---------|-------------| +| `/rollback` | List all checkpoints with change stats | +| `/rollback diff ` | Preview what changed since checkpoint N | +| `/rollback ` | Restore to checkpoint N (also undoes the last chat turn) | +| `/rollback ` | Restore a single file from checkpoint N | + +:::tip +Preview with `/rollback diff ` before restoring, and combine checkpoints with git worktrees for maximum safety — each Hermes session in its own worktree, with checkpoints as an extra layer. +::: + +## What This Threat Model Is — and Isn't + +Be clear-eyed about what these controls defend against. As the [Security](/user-guide/security#user-defined-deny-rules-approvalsdeny) guide puts it: + +> Deny rules are a guardrail against an honest-but-wrong agent, the same threat model as the dangerous-pattern detector. They are not a sandbox against a deliberately adversarial process — for that, use an isolated backend (Docker, Modal) or an egress-restricted environment. + +The same applies to the file-write guards: they apply to `write_file` and `patch` only, while the `terminal` tool runs as the same OS user. The denylist reduces accidental damage and gives models a clear stop signal; it does not sandbox a hostile or compromised agent. If your requirement is containment rather than guardrails, the answer is an isolated terminal backend — that's the boundary designed for it. + +## A Cautious Starting Config + +Everything above, assembled. Adjust to taste in `~/.hermes/config.yaml`: + +```yaml +approvals: + mode: manual # See every flagged command yourself + timeout: 300 # Unanswered prompts are denied (fail-closed) + deny: # Never-run list — survives even /yolo + - "git push --force*" + - "*curl*|*sh*" + - "dd if=* of=/dev/*" + +security: + redact_secrets: true # Already the default; stated here for clarity + +checkpoints: + enabled: true # Snapshot before destructive operations + +terminal: + backend: docker # Or ssh — keep execution off the host + docker_forward_env: [] # No host secrets inside the container +``` + +And in `~/.hermes/.env`, if you want the write sandbox: + +```bash +HERMES_WRITE_SAFE_ROOT=/path/to/project:/home/you/.hermes +``` + +## See Also + +- **[Security](/user-guide/security)** — the full defense-in-depth reference: every approval pattern, container hardening flags, gateway authorization, MCP credential filtering +- **[Checkpoints & Rollback](/user-guide/checkpoints-and-rollback)** — configuration, store maintenance, and restore workflows +- **[Tools & Toolsets](/user-guide/features/tools)** — all terminal backends and their configuration +- **[Configuration](/user-guide/configuration)** — the complete `config.yaml` reference