본문으로 건너뛰기

Security

Hermes Agent는 defense-in-depth security model을 전제로 설계되었습니다. 이 문서는 command approval, container isolation, messaging platform의 user authorization까지 Hermes가 두는 security boundary를 정리합니다.

개요

security model은 일곱 layer로 구성됩니다.

  1. User authorization - allowlist와 DM pairing으로 agent와 대화할 수 있는 사용자를 제한합니다.
  2. Dangerous command approval - destructive operation에는 human-in-the-loop approval을 요구합니다.
  3. Container isolation - Docker, Singularity, Modal sandbox에 hardened setting을 적용합니다.
  4. MCP credential filtering - MCP subprocess의 environment variable을 격리합니다.
  5. Context file scanning - project file의 prompt injection을 탐지합니다.
  6. Cross-session isolation - session 간 data와 state 접근을 막고, cron job storage path를 path traversal 공격에서 보호합니다.
  7. Input sanitization - terminal tool backend의 working directory parameter를 allowlist로 검증해 shell injection을 막습니다.

Dangerous Command Approval

Hermes는 command를 실행하기 전에 curated dangerous pattern list와 대조합니다. match가 발견되면 사용자가 명시적으로 승인해야 command가 실행됩니다.

Approval Modes

approval system은 ~/.hermes/config.yamlapprovals.mode로 설정하는 세 가지 mode를 지원합니다.

approvals:
mode: manual # manual | smart | off
timeout: 60 # seconds to wait for user response (default: 60)
ModeBehavior
manual (default)dangerous command가 발견될 때마다 사용자에게 approval prompt를 표시합니다.
smartauxiliary LLM으로 risk를 평가합니다. python -c "print('hello')" 같은 low-risk command는 auto-approve하고, 실제로 위험한 command는 auto-deny합니다. 불확실한 경우 manual prompt로 escalate합니다.
off모든 approval check를 끕니다. --yolo로 실행하는 것과 같으며, 모든 command가 prompt 없이 실행됩니다.
경고

approvals.mode: off는 모든 safety prompt를 비활성화합니다. CI/CD나 container처럼 신뢰할 수 있고 격리된 환경에서만 사용하세요.

YOLO Mode

YOLO mode는 현재 session에서 모든 dangerous command approval prompt를 우회합니다. 세 가지 방식으로 활성화할 수 있습니다.

  1. CLI flag: hermes --yolo 또는 hermes chat --yolo로 session 시작
  2. Slash command: session 중 /yolo 입력으로 on/off toggle
  3. Environment variable: HERMES_YOLO_MODE=1 설정

/yolo command는 toggle입니다. 사용할 때마다 mode가 켜지거나 꺼집니다.

> /yolo
YOLO mode ON - all commands auto-approved. Use with caution.

> /yolo
YOLO mode OFF - dangerous commands will require approval.

YOLO mode는 CLI와 gateway session 모두에서 사용할 수 있습니다. 내부적으로는 HERMES_YOLO_MODE environment variable을 설정하며, command 실행 전마다 이 값을 확인합니다.

위험

YOLO mode는 session의 모든 dangerous command safety check를 비활성화합니다. 단, 아래의 hardline blocklist는 예외로 항상 적용됩니다. disposable environment의 well-tested automation script처럼 생성되는 command를 완전히 신뢰할 수 있을 때만 사용하세요.

Hardline Blocklist (Always-On Floor)

일부 command는 irreversible filesystem wipe, fork bomb, direct block-device write처럼 너무 치명적이므로 Hermes는 다음 설정과 무관하게 항상 실행을 거부합니다.

  • --yolo / /yolo가 켜져 있음
  • approvals.mode: off
  • headless approve mode에서 실행되는 cron job
  • 사용자가 "allow always"를 클릭함

blocklist는 --yolo보다 아래에 있는 최소 안전선입니다. approval layer가 command를 보기 전에 먼저 발동하며 override flag가 없습니다. 현재 포함된 pattern은 다음과 같습니다. 이 목록은 exhaustive하지 않으며 tools/approval.py::UNRECOVERABLE_BLOCKLIST와 동기화됩니다.

PatternWhy it's hardline
rm -rf / and obvious variantsfilesystem root를 지웁니다.
rm -rf --no-preserve-root /root 삭제 의도를 명시한 variant입니다.
:(){ :|:& };: (bash fork bomb)reboot 전까지 host를 고갈시킬 수 있습니다.
mkfs.* on a mounted root devicelive system을 format합니다.
dd if=/dev/zero of=/dev/sd*physical disk를 zero-fill합니다.
Piping untrusted URLs to sh at the rootfs top levelremote-code-execution attack vector가 너무 넓어 승인 대상이 아닙니다.

blocklist에 걸리면 tool call은 agent에게 설명이 포함된 error를 반환하고 아무것도 실행하지 않습니다. wipe-and-reinstall pipeline 운영처럼 정당한 workflow에서 이런 command가 필요하다면 agent 밖에서 직접 실행하세요.

Approval Timeout

dangerous command prompt가 표시되면 사용자는 설정된 시간 안에 응답해야 합니다. timeout 안에 응답이 없으면 command는 기본적으로 거부됩니다(fail-closed).

~/.hermes/config.yaml에서 timeout을 설정합니다.

approvals:
timeout: 60 # seconds (default: 60)

What Triggers Approval

다음 pattern은 approval prompt를 trigger합니다. 정의 위치는 tools/approval.py입니다.

PatternDescription
rm -r / rm --recursiverecursive delete
rm ... /root path에서 delete
chmod 777/666 / o+w / a+wworld/other-writable permission
chmod --recursive with unsafe permsrecursive world/other-writable(long flag)
chown -R root / chown --recursive rootroot로 recursive chown
mkfsfilesystem format
dd if=disk copy
> /dev/sdblock device write
DROP TABLE/DATABASESQL DROP
DELETE FROM (without WHERE)WHERE 없는 SQL DELETE
TRUNCATE TABLESQL TRUNCATE
> /etc/system config overwrite
systemctl stop/restart/disable/masksystem service stop/restart/disable
kill -9 -1모든 process kill
pkill -9force kill processes
Fork bomb patternsfork bombs
bash -c / sh -c / zsh -c / ksh -c-c flag를 통한 shell command execution(-lc 같은 combined flags 포함)
python -e / perl -e / ruby -e / node -c-e/-c flag를 통한 script execution
curl ... | sh / wget ... | shremote content를 shell로 pipe
bash <(curl ...) / sh <(wget ...)process substitution으로 remote script 실행
tee to /etc/, ~/.ssh/, ~/.hermes/.envtee를 통한 sensitive file overwrite
> / >> to /etc/, ~/.ssh/, ~/.hermes/.envredirection을 통한 sensitive file overwrite
xargs rmrm과 xargs 조합
find -exec rm / find -deletedestructive action이 있는 find
cp/mv/install to /etc/system config로 file copy/move
sed -i / sed --in-place on /etc/system config in-place edit
pkill/killall hermes/gatewayself-termination 방지
gateway run with &/disown/nohup/setsidservice manager 밖에서 gateway를 시작하는 것을 방지
정보

Container bypass: docker, singularity, modal, daytona, vercel_sandbox backend에서 실행할 때는 dangerous command check를 건너뜁니다. container 자체가 security boundary이기 때문입니다. container 안의 destructive command는 host를 해칠 수 없습니다.

Approval Flow (CLI)

interactive CLI에서는 dangerous command가 inline approval prompt로 표시됩니다.

  DANGEROUS COMMAND: recursive delete
rm -rf /tmp/old-project

[o]nce | [s]ession | [a]lways | [d]eny

Choice [o/s/a/D]:

네 가지 option:

  • once - 이 execution 한 번만 허용
  • session - session이 끝날 때까지 이 pattern 허용
  • always - permanent allowlist에 추가(config.yaml에 저장)
  • deny (default) - command 차단

Approval Flow (Gateway/Messaging)

messaging platform에서는 agent가 dangerous command detail을 chat에 보내고 사용자의 reply를 기다립니다.

  • yes, y, approve, ok, go로 reply하면 승인합니다.
  • no, n, deny, cancel로 reply하면 거부합니다.

gateway를 실행할 때는 HERMES_EXEC_ASK=1 environment variable이 자동으로 설정됩니다.

Permanent Allowlist

"always"로 승인한 command는 ~/.hermes/config.yaml에 저장됩니다.

# Permanently allowed dangerous command patterns
command_allowlist:
- rm
- systemctl

이 pattern은 startup 시 load되며 이후 모든 session에서 조용히 승인됩니다.

permanent allowlist를 검토하거나 pattern을 제거하려면 hermes config edit을 사용하세요.

User Authorization (Gateway)

messaging gateway를 실행할 때 Hermes는 layered authorization system으로 bot과 상호작용할 수 있는 사용자를 제어합니다.

Authorization Check Order

_is_user_authorized() method는 다음 순서로 확인합니다.

  1. Per-platform allow-all flag (예: DISCORD_ALLOW_ALL_USERS=true)
  2. DM pairing approved list (pairing code로 승인된 사용자)
  3. Platform-specific allowlists (예: TELEGRAM_ALLOWED_USERS=12345,67890)
  4. Global allowlist (GATEWAY_ALLOWED_USERS=12345,67890)
  5. Global allow-all (GATEWAY_ALLOW_ALL_USERS=true)
  6. Default: deny

Platform Allowlists

허용할 user ID를 ~/.hermes/.env에 comma-separated value로 설정합니다.

# Platform-specific allowlists
TELEGRAM_ALLOWED_USERS=123456789,987654321
DISCORD_ALLOWED_USERS=111222333444555666
WHATSAPP_ALLOWED_USERS=15551234567
SLACK_ALLOWED_USERS=U01ABC123

# Cross-platform allowlist (checked for all platforms)
GATEWAY_ALLOWED_USERS=123456789

# Per-platform allow-all (use with caution)
DISCORD_ALLOW_ALL_USERS=true

# Global allow-all (use with extreme caution)
GATEWAY_ALLOW_ALL_USERS=true
경고

allowlist가 하나도 구성되지 않았고 GATEWAY_ALLOW_ALL_USERS도 설정되지 않았다면 모든 사용자가 거부됩니다. gateway는 startup 때 다음 warning을 log합니다.

No user allowlists configured. All unauthorized users will be denied.
Set GATEWAY_ALLOW_ALL_USERS=true in ~/.hermes/.env to allow open access,
or configure platform allowlists (e.g., TELEGRAM_ALLOWED_USERS=your_id).

DM Pairing System

보다 유연한 authorization을 위해 Hermes는 code-based pairing system을 제공합니다. user ID를 미리 알 필요 없이, unknown user가 one-time pairing code를 받고 bot owner가 CLI에서 승인하는 방식입니다.

How it works:

  1. unknown user가 bot에 DM을 보냅니다.
  2. bot이 8-character pairing code로 응답합니다.
  3. bot owner가 CLI에서 hermes pairing approve &lt;platform&gt; &lt;code&gt;를 실행합니다.
  4. 해당 user는 그 platform에서 permanent approval 상태가 됩니다.

unauthorized direct message 처리 방식은 ~/.hermes/config.yaml에서 제어합니다.

unauthorized_dm_behavior: pair

whatsapp:
unauthorized_dm_behavior: ignore
  • pair가 기본값입니다. unauthorized DM에는 pairing code로 reply합니다.
  • ignore는 unauthorized DM을 조용히 버립니다.
  • platform section은 global default를 override합니다. 예를 들어 Telegram에서는 pairing을 유지하면서 WhatsApp은 silent로 둘 수 있습니다.

Security features (OWASP + NIST SP 800-63-4 guidance 기반):

FeatureDetails
Code format32-character unambiguous alphabet에서 만든 8-character code. 0/O/1/I는 제외합니다.
Randomnesscryptographic randomness(secrets.choice())
Code TTL1 hour expiry
Rate limitinguser당 10분에 1 request
Pending limitplatform당 pending code 최대 3개
Lockout5 failed approval attempts -> 1-hour lockout
File security모든 pairing data file에 chmod 0600
Loggingcode는 stdout에 절대 log하지 않습니다.

Pairing CLI commands:

# List pending and approved users
hermes pairing list

# Approve a pairing code
hermes pairing approve telegram ABC12DEF

# Revoke a user's access
hermes pairing revoke telegram 123456789

# Clear all pending codes
hermes pairing clear-pending

Storage: Pairing data는 ~/.hermes/pairing/에 platform별 JSON file로 저장됩니다.

  • {platform}-pending.json - pending pairing requests
  • {platform}-approved.json - approved users
  • _rate_limits.json - rate limit and lockout tracking

Container Isolation

docker terminal backend를 사용할 때 Hermes는 모든 container에 strict security hardening을 적용합니다.

Docker Security Flags

모든 container는 다음 flag로 실행됩니다. 정의 위치는 tools/environments/docker.py입니다.

_SECURITY_ARGS = [
"--cap-drop", "ALL", # Drop ALL Linux capabilities
"--cap-add", "DAC_OVERRIDE", # Root can write to bind-mounted dirs
"--cap-add", "CHOWN", # Package managers need file ownership
"--cap-add", "FOWNER", # Package managers need file ownership
"--security-opt", "no-new-privileges", # Block privilege escalation
"--pids-limit", "256", # Limit process count
"--tmpfs", "/tmp:rw,nosuid,size=512m", # Size-limited /tmp
"--tmpfs", "/var/tmp:rw,noexec,nosuid,size=256m", # No-exec /var/tmp
"--tmpfs", "/run:rw,noexec,nosuid,size=64m", # No-exec /run
]

Resource Limits

container resource는 ~/.hermes/config.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
container_cpu: 1 # CPU cores
container_memory: 5120 # MB (default 5GB)
container_disk: 51200 # MB (default 50GB, requires overlay2 on XFS)
container_persistent: true # Persist filesystem across sessions

Filesystem Persistence

  • Persistent mode (container_persistent: true): ~/.hermes/sandboxes/docker/&lt;task_id&gt;/에서 /workspace/root를 bind-mount합니다.
  • Ephemeral mode (container_persistent: false): workspace에 tmpfs를 사용합니다. cleanup 시 모든 내용이 사라집니다.

production gateway deployment에서는 docker, modal, daytona, vercel_sandbox backend를 사용해 agent command를 host system에서 격리하세요. 그러면 dangerous command approval 자체가 필요 없어집니다.

경고

terminal.docker_forward_env에 이름을 추가하면 해당 variable은 terminal command를 위해 의도적으로 container에 주입됩니다. GITHUB_TOKEN 같은 task-specific credential에는 유용하지만, container 안에서 실행되는 code가 이를 읽고 exfiltrate할 수 있다는 뜻이기도 합니다.

Terminal Backend Security Comparison

BackendIsolationDangerous Cmd CheckBest For
local없음, host에서 직접 실행Yesdevelopment, trusted users
sshremote machineYesseparate server에서 실행
dockercontainerSkipped (container is boundary)production gateway
singularitycontainerSkippedHPC environments
modalcloud sandboxSkippedscalable cloud isolation
daytonacloud sandboxSkippedpersistent cloud workspaces
vercel_sandboxcloud microVMSkippedsnapshot persistence가 필요한 cloud execution

Environment Variable Passthrough

execute_codeterminal은 LLM-generated code가 credential을 exfiltrate하지 못하도록 child process에서 sensitive environment variable을 제거합니다. 하지만 required_environment_variables를 선언한 skill은 해당 variable에 합법적으로 접근해야 합니다.

How It Works

sandbox filter를 통과시킬 variable을 지정하는 mechanism은 두 가지입니다.

1. Skill-scoped passthrough (automatic)

skill이 skill_view 또는 /skill command로 load되고 required_environment_variables를 선언하면, 실제 environment에 설정되어 있는 variable만 자동으로 passthrough에 등록됩니다. 아직 setup-needed state라서 값이 없는 variable은 등록되지 않습니다.

# In a skill's SKILL.md frontmatter
required_environment_variables:
- name: TENOR_API_KEY
prompt: Tenor API key
help: Get a key from https://developers.google.com/tenor

이 skill을 load한 뒤에는 TENOR_API_KEYexecute_code, local terminal, **remote backends(Docker, Modal)**까지 통과합니다. manual configuration이 필요 없습니다.

Docker & Modal

v0.5.1 전에는 Docker의 forward_env가 skill passthrough와 별도 system이었습니다. 이제 두 system이 병합되었습니다. skill이 선언한 env vars는 docker_forward_env에 수동으로 추가하지 않아도 Docker container와 Modal sandbox로 자동 전달됩니다.

2. Config-based passthrough (manual)

어떤 skill도 선언하지 않은 env var를 통과시키려면 config.yamlterminal.env_passthrough에 추가하세요.

terminal:
env_passthrough:
- MY_CUSTOM_KEY
- ANOTHER_TOKEN

Credential File Passthrough (OAuth tokens, etc.)

일부 skill은 env var뿐 아니라 sandbox 안의 file이 필요합니다. 예를 들어 Google Workspace는 active profile의 HERMES_HOME 아래에 google_token.json으로 OAuth token을 저장합니다. skill은 frontmatter에서 필요한 file을 선언합니다.

required_credential_files:
- path: google_token.json
description: Google OAuth2 token (created by setup script)
- path: google_client_secret.json
description: Google OAuth2 client credentials

load 시 Hermes는 active profile의 HERMES_HOME에서 이 file들이 존재하는지 확인하고 mount 대상으로 등록합니다.

  • Docker: read-only bind mount(-v host:container:ro)
  • Modal: sandbox creation 시 mount + command 실행 전마다 sync. mid-session OAuth setup을 처리합니다.
  • Local: 별도 조치가 필요 없습니다. file이 이미 accessible합니다.

credential file을 config.yaml에 직접 나열할 수도 있습니다.

terminal:
credential_files:
- google_token.json
- my_custom_oauth_token.json

path는 ~/.hermes/ 기준 relative path입니다. container 안에서는 /root/.hermes/에 mount됩니다.

What Each Sandbox Filters

SandboxDefault FilterPassthrough Override
execute_code이름에 KEY, TOKEN, SECRET, PASSWORD, CREDENTIAL, PASSWD, AUTH가 들어간 variable 차단. safe-prefix vars만 허용passthrough vars는 두 check를 모두 bypass
terminal (local)provider keys, gateway tokens, tool API keys 같은 Hermes infrastructure vars를 명시적으로 차단passthrough vars는 blocklist bypass
terminal (Docker)기본적으로 host env vars를 전달하지 않음passthrough vars + docker_forward_env-e로 forwarded
terminal (Modal)기본적으로 host env/file을 전달하지 않음credential files mount, env passthrough sync
MCPsafe system vars와 explicit env config를 제외한 모든 env 차단passthrough의 영향을 받지 않음. MCP env config를 사용

Security Considerations

  • passthrough는 사용자 또는 skill이 명시적으로 선언한 variable에만 적용됩니다. arbitrary LLM-generated code에 대한 기본 security posture는 유지됩니다.
  • credential files는 Docker container에 read-only로 mount됩니다.
  • Skills Guard는 설치 전 skill content에서 suspicious env access pattern을 scan합니다.
  • missing/unset vars는 등록되지 않습니다. 존재하지 않는 값은 leak될 수 없습니다.
  • Hermes infrastructure secrets(provider API keys, gateway tokens)는 env_passthrough에 추가하지 마세요. 해당 secret들은 dedicated mechanism을 갖고 있습니다.

MCP Credential Handling

MCP(Model Context Protocol) server subprocess는 accidental credential leakage를 막기 위해 filtered environment를 받습니다.

Safe Environment Variables

host에서 MCP stdio subprocess로 전달되는 variable은 다음뿐입니다.

PATH, HOME, USER, LANG, LC_ALL, TERM, SHELL, TMPDIR

여기에 XDG_* variable이 추가됩니다. 그 외 environment variable(API keys, tokens, secrets)은 stripped됩니다.

MCP server의 env config에 명시한 variable은 전달됩니다.

mcp_servers:
github:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-github"]
env:
GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_..." # Only this is passed

Credential Redaction

MCP tool error message는 LLM에 반환되기 전에 sanitize됩니다. 다음 pattern은 [REDACTED]로 대체됩니다.

  • GitHub PATs (ghp_...)
  • OpenAI-style keys (sk-...)
  • Bearer tokens
  • token=, key=, API_KEY=, password=, secret= parameters

Website Access Policy

web과 browser tool을 통해 agent가 접근할 수 있는 website를 제한할 수 있습니다. internal service, admin panel, sensitive URL 접근을 막을 때 유용합니다.

# In ~/.hermes/config.yaml
security:
website_blocklist:
enabled: true
domains:
- "*.internal.company.com"
- "admin.example.com"
shared_files:
- "/etc/hermes/blocked-sites.txt"

blocked URL이 요청되면 tool은 policy에 의해 domain이 blocked되었다는 error를 반환합니다. blocklist는 web_search, web_extract, browser_navigate, 그리고 URL-capable tool 전체에 적용됩니다.

전체 내용은 configuration guide의 Website Blocklist를 참고하세요.

SSRF Protection

모든 URL-capable tools(web search, web extract, vision, browser)는 Server-Side Request Forgery(SSRF)를 막기 위해 fetch 전에 URL을 검증합니다. 차단되는 address는 다음과 같습니다.

  • Private networks (RFC 1918): 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
  • Loopback: 127.0.0.0/8, ::1
  • Link-local: 169.254.0.0/16 (169.254.169.254 cloud metadata 포함)
  • CGNAT / shared address space (RFC 6598): 100.64.0.0/10 (Tailscale, WireGuard VPNs)
  • Cloud metadata hostnames: metadata.google.internal, metadata.goog
  • Reserved, multicast, and unspecified addresses

SSRF protection은 internet-facing use에서 항상 활성화되며 DNS failure는 blocked로 처리됩니다(fail-closed). redirect-based bypass를 막기 위해 redirect chain의 각 hop도 다시 검증합니다.

Intentionally allowing private URLs

일부 setup은 private/internal URL 접근이 정당하게 필요합니다. 예를 들어 home.arpa가 RFC 1918 address로 resolve되는 home network, LAN-only Ollama/llama.cpp endpoint, internal wiki, cloud metadata debugging 등이 있습니다. 이런 경우 global opt-out을 사용할 수 있습니다.

security:
allow_private_urls: true # default: false

이 값을 켜면 web tools, browser, vision URL fetch, gateway media download가 RFC 1918 / loopback / link-local / CGNAT / cloud-metadata destination을 더 이상 reject하지 않습니다. 이 설정은 명시적인 trust boundary입니다. agent가 prompt-injected URL을 local network에 임의로 요청해도 감수할 수 있는 machine에서만 enable하세요. public-facing gateway에서는 꺼 두는 것이 맞습니다.

underlying IP가 public이어도 lookalike Unicode domain trick을 막는 host-substring guard는 이 설정과 무관하게 계속 켜져 있습니다.

Tirith Pre-Exec Security Scanning

Hermes는 command 실행 전 content-level scanning을 위해 tirith를 통합합니다. Tirith는 단순 pattern matching만으로 놓치기 쉬운 threat를 탐지합니다.

  • Homograph URL spoofing(internationalized domain attacks)
  • Pipe-to-interpreter patterns(curl | bash, wget | sh)
  • Terminal injection attacks

Tirith는 첫 사용 시 GitHub releases에서 자동 설치되며 SHA-256 checksum verification을 수행합니다. cosign을 사용할 수 있으면 cosign provenance verification도 수행합니다.

# In ~/.hermes/config.yaml
security:
tirith_enabled: true # Enable/disable tirith scanning (default: true)
tirith_path: "tirith" # Path to tirith binary (default: PATH lookup)
tirith_timeout: 5 # Subprocess timeout in seconds
tirith_fail_open: true # Allow execution when tirith is unavailable (default: true)

tirith_fail_open이 기본값인 true이면 tirith가 설치되어 있지 않거나 timeout이 나도 command는 계속 진행됩니다. high-security environment에서는 tirith를 사용할 수 없을 때 command를 차단하도록 false로 설정하세요.

Tirith는 Linux(x86_64 / aarch64)와 macOS(x86_64 / arm64)용 prebuilt binary를 제공합니다. Windows처럼 prebuilt binary가 없는 platform에서는 tirith를 조용히 건너뜁니다. pattern-matching guard는 계속 실행되며, CLI는 "unavailable" banner를 표시하지 않습니다. Windows에서 tirith를 쓰려면 WSL에서 Hermes를 실행하세요.

Tirith verdict는 approval flow와 통합됩니다. safe command는 그대로 통과하고, suspicious 또는 blocked command는 tirith findings(severity, title, description, safer alternatives)와 함께 user approval을 trigger합니다. 사용자는 approve 또는 deny할 수 있으며, unattended scenario를 안전하게 유지하기 위해 기본 선택은 deny입니다.

Context File Injection Protection

Context files(AGENTS.md, .cursorrules, SOUL.md)는 system prompt에 포함되기 전에 prompt injection scan을 거칩니다. scanner는 다음을 확인합니다.

  • 이전 instruction을 ignore/disregard하라는 지시
  • suspicious keyword가 들어 있는 hidden HTML comments
  • secret(.env, credentials, .netrc)을 읽으려는 시도
  • curl을 통한 credential exfiltration
  • invisible Unicode characters(zero-width spaces, bidirectional overrides)

차단된 file은 다음 warning을 보여줍니다.

[BLOCKED: AGENTS.md contained potential prompt injection (prompt_injection). Content not loaded.]

Best Practices for Production Deployment

Gateway Deployment Checklist

  1. Set explicit allowlists - production에서는 GATEWAY_ALLOW_ALL_USERS=true를 사용하지 마세요.
  2. Use container backend - config.yaml에서 terminal.backend: docker를 설정하세요.
  3. Restrict resource limits - 적절한 CPU, memory, disk limit을 설정하세요.
  4. Store secrets securely - API key는 적절한 file permission을 가진 ~/.hermes/.env에 보관하세요.
  5. Enable DM pairing - 가능하면 user ID hardcoding 대신 pairing code를 사용하세요.
  6. Review command allowlist - config.yamlcommand_allowlist를 주기적으로 audit하세요.
  7. Set MESSAGING_CWD - agent가 sensitive directory에서 동작하지 않도록 하세요.
  8. Run as non-root - gateway를 root로 실행하지 마세요.
  9. Monitor logs - unauthorized access attempt가 없는지 ~/.hermes/logs/를 확인하세요.
  10. Keep updated - security patch를 위해 hermes update를 정기적으로 실행하세요.

Securing API Keys

# Set proper permissions on the .env file
chmod 600 ~/.hermes/.env

# Keep separate keys for different services
# Never commit .env files to version control

Network Isolation

최대 보안을 원하면 gateway를 별도 machine이나 VM에서 실행하세요. config.yaml에서 terminal.backend: ssh를 설정하고, host detail은 ~/.hermes/.env의 environment variable로 제공합니다.

# ~/.hermes/config.yaml
terminal:
backend: ssh
# ~/.hermes/.env
TERMINAL_SSH_HOST=agent-worker.local
TERMINAL_SSH_USER=hermes
TERMINAL_SSH_KEY=~/.ssh/hermes_agent_key

SSH connection detail은 config.yaml이 아니라 .env에 둡니다. profile export와 함께 check-in되거나 공유되지 않도록 하기 위함입니다. 이 구조는 gateway의 messaging connection과 agent command execution을 분리합니다.