📑 Table of contents

Security and Permissions in Hermes Agent

Hermes Agent 🔴 Advanced ⏱️ 11 min read 📅 2026-05-05

Introduction

Hermes Agent has full access to your system: shell command execution, file reading and writing, network access, SQL queries, database manipulation. This power comes with responsibility. If a malicious model or a simple hallucination generates a destructive command, the consequences can be irreversible.

That's why Hermes integrates a multi-layer security model designed to protect your system without hindering productivity. This article details each layer: command approvals, advanced security scanner, secret redaction in logs, web access filtering, and best practices for secure deployment.

The command approval system

Every command executed by Hermes via the terminal tool passes through a multi-level detection and approval system. This is the core of Hermes' operational security.

Two danger levels

Hermes distinguishes two command categories with radically different treatments:

HARDLINE_PATTERNSdefinitively blocked commands, even in YOLO mode:

  • rm -rf /, rm -rf /home, rm -rf /etc, rm -rf /usr — recursive deletion of system or home directories
  • mkfs — filesystem formatting
  • dd of=/dev/sda, > /dev/sda — raw writes or redirects to block devices
  • Fork bombs (:(){ :|:& };:)
  • kill -1, shutdown, reboot, halt, poweroff — system shutdown or reboot
  • systemctl poweroff/reboot/halt, init 0/6, telinit 0/6

These commands are blocked without exception. No configuration mode allows bypassing them. This is absolute protection against catastrophic scenarios.

DANGEROUS_PATTERNSpotentially dangerous commands requiring explicit approval:

  • Deletion: rm -r, find -delete, find -exec rm, xargs rm
  • Permissions: chmod 777, chmod 666, chmod o+w, chown -R root
  • Destructive SQL operations: DROP TABLE, DELETE FROM without WHERE clause, TRUNCATE
  • Remote content execution: curl | sh, wget | bash, process substitution with $(curl...)
  • Script execution: bash -c, python -c, perl -e, node -e, heredocs (python3 << 'EOF')
  • Writing to sensitive paths: /etc/, .env files, .ssh/, .bashrc/.zshrc, system configs
  • Destructive Git operations: git push --force, git reset --hard, git clean -f, git branch -D
  • Processes: pkill -9, killall, kill -9 -1
  • System services: sudo, systemctl stop/restart/disable
  • Execution after chmod +x: detects the chmod +x && ./script pattern

These commands trigger an approval prompt (in CLI) or a notification (in gateway) before execution.

Self-termination protection

Hermes protects itself against commands that would kill it:

  • pkill hermes, killall hermes — terminating the Hermes process
  • hermes gateway stop, hermes update — stopping or updating which kills running agents
  • kill $(pgrep -f hermes) — PID expansion to bypass name-based patterns
  • Starting gateway outside systemd (gateway run &, nohup gateway run)

This protection ensures that work in progress isn't involuntarily interrupted by an agent-generated command.

Approval modes

Three modes are available via configuration:

# In ~/.hermes/config.yaml
approvals:
  mode: manual       # manual | smart | off
  timeout: 60        # seconds before auto-deny
  cron_mode: deny    # deny | approve (cron job behavior)

Manual mode (default): each command detected as dangerous triggers an interactive prompt with four choices:

  • once — execute the command a single time
  • session — allow all commands matching this pattern for the current session
  • always — permanently allow this pattern (saved to config.yaml)
  • deny — reject the command

Long commands (> 70 characters) offer an additional view choice to inspect the full command before deciding.

Smart mode: an auxiliary LLM evaluates the actual risk of the command. This mode, inspired by OpenAI Codex's Smart Approvals system, solves the frequent false positive problem. For example, python -c "print('hello')" is detected as dangerous by the regex pattern (execution via -c flag), but the LLM understands it's a harmless print and auto-approves it.

The LLM receives the command and the flag reason, then returns:
- approve — the command is clearly safe
- deny — the command is genuinely dangerous
- escalate — uncertain, returns to manual approval

Off mode: DANGEROUS commands execute without approval. HARDLINE commands remain blocked. Reserve this mode for disposable environments.

Permanent approval (allowlist)

When you choose always for a command, the pattern is saved to your configuration:

approvals:
  permanent_allowlist:
    - "recursive delete"
    - "world/other-writable permissions"

Commands matching these patterns are automatically approved without prompts. Pattern aliases are managed automatically for backward compatibility.

YOLO mode

YOLO mode (/yolo in session or --yolo at launch) disables all approvals for DANGEROUS_PATTERNS commands:

/yolo     # Toggle ON/OFF in session
hermes --yolo   # Launch directly in YOLO mode

HARDLINE commands remain blocked even in YOLO — this is the last line of defense.

⚡ Only use YOLO mode in isolated environments (Docker containers, disposable VMs). Never enable it on your production machine or main VPS.

Approvals in gateway mode

In gateway mode (Telegram, Discord, Slack, etc.), approvals work via dedicated commands:

  • /approve — validate a pending command
  • /deny — reject a pending command
  • A configurable timeout (default: 60 seconds) automatically rejects unvalidated commands
  • Tirith warnings hide the always option in the prompt (no permanent allowlisting for content threats)

Smart mode is particularly recommended in gateway to avoid blocking the agent on false positives while you're away from the screen.

Cron job behavior

Cron tasks run without human interaction. The cron_mode parameter defines their behavior when facing dangerous commands:

approvals:
  cron_mode: deny     # Block all dangerous commands (default, recommended)
  # cron_mode: approve # Execute without approval (risky)

In deny mode (recommended), dangerous commands are silently rejected. Cron prompt design: avoid risky operations in your scheduled tasks, or use restricted toolsets to limit available tools for the cron job.

Tirith: the advanced security scanner

Tirith is an external security tool integrated into Hermes that performs semantic command analysis beyond simple regex patterns.

What is Tirith?

Tirith detects content-level threats that regex-based patterns cannot catch:

  • Homograph URLs — Unicode characters visually identical to ASCII characters (e.g., Cyrillic «а» instead of Latin «a») used to bypass filters
  • Terminal injections — ANSI escape sequences hidden in commands that could modify display or execute unintended actions
  • Interpreter pipes via obfuscation techniques not covered by classic patterns
  • Structural threats — commands whose danger depends on combining multiple elements

Configuration

# In ~/.hermes/config.yaml
security:
  tirith_enabled: true       # Enabled by default
  tirith_path: tirith        # Binary path (auto-installed if missing)
  tirith_timeout: 5          # Analysis timeout in seconds
  tirith_fail_open: true     # Behavior on failure

Auto-installation

If Tirith isn't found on the system, Hermes automatically downloads it from GitHub releases (sheeki03/tirith) with SHA-256 verification. If the cosign tool is available, provenance is also verified (GitHub Actions workflow signature). Installation runs in a background thread so it never blocks startup.

Verdicts

Tirith returns three exit codes:

  • allow (0) — the command passes without warning
  • warn (2) — warning: requires approval, but the always option is hidden (content threats shouldn't be permanently allowlisted)
  • block (1) — blocks the command with a detailed description of findings

Fail-open vs fail-closed

The tirith_fail_open parameter defines behavior when Tirith crashes or exceeds the timeout:

  • true (default) — the command is allowed: prioritizes availability
  • false — the command is blocked: prioritizes security

For critical production environments, use false for fail-closed behavior. In development, true avoids unnecessary blocking.

Secret redaction in logs

Hermes integrates automatic secret redaction to prevent API keys, tokens, and credentials from leaking into logs, verbose output, and gateway logs.

Activation

# In ~/.hermes/config.yaml
security:
  redact_secrets: true   # Disabled by default — enable in gateway

Activation is done via security.redact_secrets: true, which is bridged to the HERMES_REDACT_SECRETS environment variable. The check is snapshotted at startup — an LLM cannot enable/disable redaction mid-session.

Detection patterns

The system automatically recognizes token formats from 30+ providers:

Common API keys:
- sk-* — OpenAI, OpenRouter, Anthropic
- ghp_*, github_pat_*, gho_*, ghs_*, ghu_*, ghr_* — GitHub
- xox[baprs]-* — Slack
- AIza* — Google API
- AKIA* — AWS Access Key ID
- sk_live_*, sk_test_* — Stripe
- pplx-*, fal_*, fc-* — Perplexity, Fal.ai, Firecrawl

Sensitive parameters in URLs and bodies:
- Query strings: ?api_key=, ?token=, ?secret=, ?password=, ?client_secret=
- JSON/form bodies: access_token, refresh_token, authorization, private_key fields

Redaction logic

  • Short tokens (< 18 characters): fully masked (***)
  • Long tokens: first 6 and last 4 characters preserved for debugging

Example: sk-ant-api03-xxxxx...abcd

Website Blocklist: web access filtering

Hermes can block access to specific domains via browser and web tools, protecting against unwanted or malicious access.

Configuration

# In ~/.hermes/config.yaml
security:
  website_blocklist:
    enabled: true
    domains:
      - evil-site.com
      - phishing-example.org
      - "*.suspicious-domain.net"
    shared_files:
      - /path/to/community-blocklist.txt

How it works

  • Domains are compared with wildcard support (*.example.com)
  • The www. prefix is automatically stripped for comparison
  • Shared files contain one domain per line (lines starting with # are comments)
  • Policy is cached for 30 seconds to avoid re-reading the YAML file on every request
  • A missing or unreadable file generates a warning but doesn't block web tools

Private URLs and localhost access

By default, Hermes blocks navigation to private URLs from the browser to prevent SSRF (Server-Side Request Forgery) attacks:

# In ~/.hermes/config.yaml
security:
  allow_private_urls: false   # Block localhost (default)

The browser.auto_local_for_private_urls parameter (default true) allows using local Chromium automatically for LAN/localhost URLs, bypassing remote browser services and avoiding unnecessary network latency.

Security best practices

Docker isolation

The most effective way to secure Hermes is to use the Docker terminal backend:

hermes config set terminal.backend docker

All commands execute in an isolated container. An rm -rf / only deletes the container's filesystem, not your host system. This is the simplest and most robust protection.

A Hostinger VPS with 2 vCPU and 4 GB RAM is sufficient to run Hermes with the Docker backend and gateway in always-on mode.

Least privilege principle

  • Create a dedicated user for Hermes instead of running it as root
  • Limit enabled toolsets: hermes tools disable web if the browser isn't needed
  • Use scoped API keys (limited permissions) instead of full-access keys
  • Separate environments: one profile for development, one for production

Monitoring and audit

# Check security logs
hermes logs --level warning | grep -i "approval\|dangerous\|tirith"

# Check permanent approvals
hermes config | grep -A20 approvals

# View recently approved commands
grep "approval" ~/.hermes/logs/agent.log | tail -20

Here's a secure configuration for an always-on Hermes gateway:

# ~/.hermes/config.yaml — secure setup for gateway
security:
  tirith_enabled: true
  tirith_fail_open: false      # Fail-closed in production
  redact_secrets: true          # Always enable in gateway
  allow_private_urls: false
  website_blocklist:
    enabled: true
    domains: []
    shared_files: []

approvals:
  mode: smart                  # Auto-approve false positives
  timeout: 60
  cron_mode: deny              # Block dangerous commands in cron

terminal:
  backend: docker              # Command isolation

Conclusion

Hermes Agent integrates a multi-layer security model that protects your system without sacrificing productivity. The two-level approval system (unpassable hardline + flexible dangerous approvals), combined with the Tirith scanner for semantic threats and automatic secret redaction, provides comprehensive protection against unintentional commands, data leaks, and unauthorized access.

Key takeaways:

  • Never disable approvals on a production system — use smart mode for optimal balance
  • Enable redact_secrets: true as soon as you use Hermes in gateway mode
  • Use the Docker backend for complete shell command isolation
  • Set tirith_fail_open: false in critical production environments for fail-closed behavior
  • Design your cron jobs with prompts that don't trigger any dangerous commands

To learn more about tool management, check out our article on available tools in Hermes Agent and discover how checkpoints let you roll back accidental modifications.