Command approval
Before executing any terminal command, Hermes checks it against a list of dangerous patterns. When a match is found, execution is paused and you’re asked to approve or deny.How detection works
The dangerous command detector (tools/approval.py) scans every shell command against a set of regex patterns before it runs. Matched categories include:
| Pattern | Description |
|---|---|
rm -r | Recursive delete |
chmod 777 | World-writable permissions |
chown -R root | Recursive chown to root |
mkfs | Format filesystem |
dd if= | Disk copy |
DROP TABLE/DATABASE | SQL DROP |
DELETE FROM (no WHERE) | SQL DELETE without WHERE clause |
TRUNCATE TABLE | SQL TRUNCATE |
Write to /etc/ | Overwrite system config |
systemctl stop/disable | Stop or disable a system service |
kill -9 -1 | Kill all processes |
| Fork bomb pattern | :()\{ :|:& \};: |
bash -c, sh -c | Shell via -c flag |
python -e, python -c | Script execution via -e/-c |
curl | bash | Pipe remote content to shell |
find -exec rm | find with rm exec |
Approval choices
When a dangerous command is detected, you’ll be presented with:- Once — allow this specific command, this time only
- Session — approve this command pattern for the rest of the current session
- Always — add the pattern to your permanent allowlist (saved to
config.yaml) - Deny — block the command; the agent is told it was rejected and must not retry
Approval modes
Configure the approval mode in~/.hermes/config.yaml:
| Mode | Behavior |
|---|---|
manual | Always prompt the user (default) |
smart | An auxiliary LLM assesses risk first; auto-approves low-risk matches, prompts for high-risk ones |
off | Skip all approval prompts (equivalent to --yolo) |
Smart mode is inspired by the OpenAI Codex Smart Approvals guardian subagent. It uses your configured auxiliary model (fast/cheap recommended) to assess whether a flagged command is a false positive before interrupting you.
Command allowlist
Patterns approved with “Always” are saved to thecommand_allowlist in config.yaml:
~/.hermes/config.yaml directly and remove the line from command_allowlist.
Tirith pre-exec scanning
Hermes optionally integrates with tirith for additional pre-execution security scanning. Tirith detects homograph URLs, pipe-to-shell patterns, terminal injection, and environment manipulation. Install tirith:config.yaml:
warn finding, it’s combined with the dangerous command check into a single approval prompt. When tirith issues a block, the command is rejected immediately with no approval option.
API key security
All API keys are stored in~/.hermes/.env, which is created with 0600 permissions (owner read/write only). The directory ~/.hermes/ itself uses 0700 permissions.
config.yaml, never committed to version control, and never exposed to the agent in tool outputs. By default, Hermes redacts secrets from terminal output:
redact_secrets: false only for debugging authentication issues.
Security for messaging platforms
Allowed users
Every platform supports an allowlist of user IDs. Messages from users not on the list are silently ignored.DM pairing
DM pairing is a code-based authorization mechanism. When enabled, users must send a one-time pairing code (generated out-of-band) before they can interact with the bot. This is useful for giving access to people without knowing their platform user IDs in advance. Pairing state is managed by thePairingStore and persists across gateway restarts.
Telegram-specific security
Telegram-specific security
By default the Telegram bot responds to anyone who messages it unless
TELEGRAM_ALLOWED_USERS is set. Always set an allowlist for bots on public Telegram.For group chats, the bot only responds to messages that mention it or are direct commands. Each participant in a group gets their own isolated session by default (group_sessions_per_user: true in config.yaml).Discord-specific security
Discord-specific security
In server channels the bot requires an @mention to respond by default:DMs do not require a mention.
Slack-specific security
Slack-specific security
Slack access is controlled by
SLACK_ALLOWED_USERS. The bot is invoked via /hermes <subcommand> or by mentioning it in a channel.Required OAuth scopes constrain what the bot can see: it only reads channels and DMs it is invited to.Email-specific security
Email-specific security
The
EMAIL_ALLOWED_USERS list is compared to the From: header of incoming emails. Only emails from listed addresses trigger the agent.For Gmail, use an App Password rather than your account password — App Passwords can be revoked independently.Container isolation
Running Hermes with a container terminal backend (Docker, Singularity, Modal, or Daytona) provides strong isolation: the agent executes all terminal commands inside the container, not on your host machine. Configure the terminal backend in~/.hermes/config.yaml:
What isolation provides
- Agent cannot read
~/.hermes/.env(API keys stay on the host) - Agent cannot modify its own code
- Destructive commands are contained within the container filesystem
- Container is destroyed or reset at the end of the session (when
container_persistent: false)