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_PATTERNS — definitively blocked commands, even in YOLO mode:
rm -rf /,rm -rf /home,rm -rf /etc,rm -rf /usr— recursive deletion of system or home directoriesmkfs— filesystem formattingdd of=/dev/sda,> /dev/sda— raw writes or redirects to block devices- Fork bombs (
:(){ :|:& };:) kill -1,shutdown,reboot,halt,poweroff— system shutdown or rebootsystemctl 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_PATTERNS — potentially 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 FROMwithout 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/,.envfiles,.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 thechmod +x && ./scriptpattern
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 processhermes gateway stop,hermes update— stopping or updating which kills running agentskill $(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 availabilityfalse— 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 webif 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
Recommended production configuration
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: trueas soon as you use Hermes in gateway mode - Use the Docker backend for complete shell command isolation
- Set
tirith_fail_open: falsein 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.