セルフホスト版 Hermes Agent の security ガイド
こんにちは、Lena です。ひとつの config file に触れる前に、午後のかなりの時間を使って security ページを読みました。それから、もう一度読み返しました。最初に読んだときは、この system は長い options の一覧のように見えました。二度目に読んだとき、ようやく全体の形が見えてきました。Hermes Agent security にあるのは、実はひとつの「security feature」ではなく、互いに独立した layers の積み重ねです。それぞれの layer は、他の layer が失敗する可能性を前提にしています。
この見方は、思っていた以上に重要でした。これまで見てきた agent security の記事の多くは、tips の checklist のように読めます。これをオンにする、あの flag を設定する、これで大丈夫、という感じです。でも Hermes の documentation は少し違います。これは defense-in-depth model です。各 layer はひとつの具体的な仕事を担当していて、どれかひとつを有効にしても、他の layer の代わりにはなりません。どの layer も、それ単体では答えになりません。 この一文が、ほとんどこの記事全体です。
これは、長期間動かす self-hosted Hermes deployment をどう harden するかについて、私が考えていることのメモです。まだ分かっていない部分もあります。
Hermes security model を layer で見る
公式 security ページ を丁寧に読むと、この model にはおおよそ七つの独立した layers があります。そしてここでいう「独立」は、かなり重要です。各 layer は、何が壊れうるかについて別々の前提を持っています。tool call の中でおおよそ適用される順番に並べると、こうなります。
- ユーザー認可 — そもそも誰が agent と話せるのかを gateway-level で確認する
- 危険コマンド approval — shell commands が実行される前に pattern-based detection を行う
- Tirith content scanner — prompt-injection、credential exfil、terminal-injection patterns を pre-execution で検査する Rust-based scanner
- Runtime isolation — local vs Docker vs SSH vs Modal vs Daytona vs Singularity
- Credential filtering — child processes への env-var stripping、MCP subprocess env allowlists、output redaction
- Context file scanning — AGENTS.md、SOUL.md、.cursorrules を load time に prompt injection として scan する
- Cross-session isolation — sessions は互いの state を読めない。cron paths は traversal に対して harden されている
この点に何度も戻ってきます。なぜなら、ある問題を捕まえる layer は、必ずしも自分が想定していた layer ではないからです。 悪意ある shell command は approval に止められるかもしれません。Tirith に止められるかもしれません。container に止められるかもしれません。三つすべてかもしれないし、ときにはどれにも止められないかもしれません。だから、ひとつをオフにしても安全に見えるのです。そうでなくなる瞬間までは。
この原則自体は、agents よりずっと古いものです。CISA の Secure by Design joint guidance は secure defaults について語っています。out-of-the-box configuration は安全であるべきで、そこから外れる場合は明示的であるべきだ、という考え方です。Hermes はおおむねこれに従っています。approvals は default でオン、Tirith は high-security mode で fail closed、gateway は allowlist がない場合に全 users を deny します。ただし、この「おおむね」が曲者です。deviations は重要です。
危険コマンド approval と、それが効く場所
ここは少し慎重に書きたいところです。Approval prompts は安心感をくれます。そして、だからこそ過信しやすいのです。
Hermes は危険な commands の regex patterns を持っています。たとえば rm -rf、DROP TABLE、fork bombs、curl output を bash に pipe するもの、gateway process を kill するものなどです。match すると、user に approval が求められます。mode は三つあります。manual(常に聞く)、smart(LLM-assisted risk scoring)、off(聞かない)。さらに、その session で全てを bypass する /yolo もあります。
私がずっと自分に言い聞かせているのは、regex-based detection は本質的に bypass 可能だということです。 command は obfuscate できます。base64-encode できます。二つの tool call に分割できます。file に書き出してから source することもできます。Hermes は scan の前に input を normalize します(ANSI escapes、null bytes、NFKC Unicode を strip します)。これで分かりやすい obfuscation paths は塞がれます。それでも、open-ended attack surface に対する pattern matching であることは変わりません。
Hermes GitHub で最近行われた community security audit は、この点を詳しく扱っていました。finding は、Hermes が unsafe だというものではありません。default configuration is permissive であり、user が harden することを前提にしている、というものでした。これは擁護できる design choice です。同時に、deployment を運用する人にかなり現実的な責任を置く選択でもあります。
なので、今の私は approval をこう見ています。これは事故のための tripwire であって、adversarial agent への defense ではありません。tool access を持つ model が unintentional に外れたとき——wrong path、missing flag、自信満々だけれど間違った command——approval はそれを捕まえます。一方で、model の input が本当に compromised されているなら、approval は頼るべき layer ではありません。Approval prompt は human-in-the-loop の seatbelt です。container は crumple zone です。
Runtime isolation choices
ここは Hermes が本当に選択肢をくれるところで、この選択は他の多くの項目より重いです。terminal backend は、「agent が command を実行した」ということが物理的に何を意味するのかを決めます。
local— host 上で commands を実行します。Default です。Approval prompts は active。Blast radius は host です。docker— commands は container 内で実行されます。read-only root、dropped capabilities、configurable CPU/memory/disk。Dangerous command checks は unconditionally skipped されます。container 自体が boundary だからです。ssh— remote machine 上で commands を実行します。agent を laptop から完全に離したいときに便利です。modalとdaytona— idle 時に hibernate する serverless backends です。Container-class isolation と near-zero idle cost。singularity— Docker が使えない HPC environments 向けです。
いくつか、取り出しておきたい点があります。approval prompts の "container bypass" は意図的なものです。team の reasoning は、container が保つなら inner regex check は redundant であり、container が破れるなら regex では救えない、というものです。納得するまで少し時間がかかりました。
Docker を選ぶ場合、Hermes config が提供する hardening levers は Docker 公式 engine security docs の standard practices とかなり対応しています。namespace isolation、dropped capabilities、read-only root、resource limits。Default Hermes Docker image では、これらが有効になっています。人がよくやる間違いは、そこにまた何かを戻してしまうことです。 terminal.docker_forward_env が分かりやすい例です。container に forward した variable は、すべて agent が読めて exfiltrate できます。default allowlist は empty です。task-specific tokens 以外では、そのままにしておきたいです。
Persistent vs ephemeral mode も分かれ道です。Persistent は workspace directory を runs の間で bind-mount するので、agent は state を build できます。development には便利です。Ephemeral は tmpfs を使うので、container が止まればすべて消えます。production に近いものにはこちらが向いています。判断基準はこうです。悪意ある file が ~/.hermes/sandboxes/ に一週間残っていて、あとから気づくとしても大丈夫かどうか。
Messaging と MCP security boundaries
Hermes が gateway として動くとき、「誰がそれと話せるのか」は実際の問題になります。authorization model は layered です。per-platform allow-all flags、DM pairing approved list、platform allowlists、global allowlist。これらが何も configured されていない場合、default は deny everyone で、startup warning が出ます。これは正しい default です。そして一部の self-host guides が testing のために GATEWAY_ALLOW_ALL_USERS=true を設定させ、そのまま戻し忘れさせることは、それだけでひとつの incident category です。
DM pairing は、人に勧めることが多い部分です。Telegram/Discord IDs の list を自分で維持する代わりに、unknown user は one-time pairing code を受け取り、あなたが CLI から hermes pairing approve telegram ABC12DEF で approve します。Hermes docs は、この design が OWASP と NIST SP 800-63 digital identity guidance を参考にしていると説明しています。codes は one-time で time-bounded、approval action は explicit です。新しい発明ではありません。でも、access decisions が事前に config files を編集することでなく、request を見ている実際の人間によって行われる、という意味があります。
MCP は、それだけで別の surface です。私がいちばん時間をかけて理解したことは、Hermes の中の MCP tool は、agent の permissions ではなく、その背後にいる server の permissions で動くという点です。 それこそが protocol の目的です。しかし同時に、接続されている各 MCP server が別々の trust decision になる、ということでもあります。
Hermes の MCP config reference には、今の私が non-optional だと考えている protections が二つあります。ひとつ目は environment filtering です。default では、PATH、HOME、USER、LANG、LC_ALL、TERM、SHELL、TMPDIR、XDG_* だけが MCP stdio subprocesses に pass through されます。それ以外——API keys、tokens——は stripped されます。本当に必要な variables は、server の explicit env block に入れます。二つ目は、include と exclude による per-server tool filtering です。server が 20 tools を expose していて、agent が 3 つしか必要としないなら、その 3 つだけを allowlist します。
三つ目は config ではなく、discipline です。Context files(AGENTS.md、SOUL.md、.cursorrules)は、system prompt に load される前に prompt injection patterns を scan されます。これは OWASP's LLM Top 10 が indirect prompt injection と呼ぶ問題 に対応する layer です。model に読ませる content の中に instructions が隠れている、という問題です。scanner は complete defense ではありません(この category で complete なものはありません)。でも、その check が存在する場所としては正しく、default で on です。
Self-hosted Hermes deployment を harden する
私が最終的に使うようになった patterns を、大まかな priority order で並べます。
non-root user として実行し、passwordless sudo は必要な場所だけにします。 Hermes installer はこれを前提にしています。security model もこれを前提にしています。gateway を root で実行しないでください。
runtime isolation は convenience ではなく trust model に合わせて選びます。 scheduled jobs を主に実行し、messages に応答する server なら、Docker backend、empty docker_forward_env、ephemeral workspace、minimal mounted volumes が、地味ですが正しい選択です。Local backend は、personal laptop で各 approval prompt を見ているなら reasonable です。積極的に見ていない VPS では、default としては悪い選択です。
secrets を broad scopes に置かないでください。 Provider API keys と gateway tokens は ~/.hermes/.env に置き、permissions は 0600 にします。env_passthrough には入れません。docker_forward_env にも入れません。MCP servers が受け取るのは、それぞれの env block が explicit に named した variables だけです。
user authorization を明示的に configure します。 本当に許可したい user IDs で platform allowlists を設定するか、DM pairing を使います。production environment に GATEWAY_ALLOW_ALL_USERS=true を残してはいけません。それは testing flag です。
オフにした layers を audit します。 approvals.mode: off と /yolo には存在理由があります。CI runs、sandboxed test environments などです。でも、どちらかが live config にあるなら、その理由を書き留めてください。tirith_enabled: false も同じです。価値は、それらが on かどうかではありません。なぜそうしていないのかを説明できることです。
Update discipline は initial config より重要です。 Hermes は頻繁に shipped され、recent release のほぼすべてに security improvements が入っています。secret-exfil blocking、expanded credential directory protections、broader token redaction patterns、browser URL exfil blocks。六か月前の install は、どれだけ慎重に setup していても、より悪い install です。
これは今後も refine していきます。まだ完全には理解していない layers もあります。Tirith の verdict-to-approval handoff はもっと時間をかけたい部分ですし、自分自身の long-running deployment を本当に audit pass したこともまだありません。ただ、layered model が正しいこと、そして個々の layer がそれ単体で答えではないことには、かなり確信があります。 ひとつの trick だけを渡してくる writeup があるなら、おそらくそれは間違っています。
FAQ
approvals.mode: off で動かすべきですか?
container または sandbox の中で、その container が仕事をしている場合だけです。local backend では、いいえ。
Docker backend は approval prompts の完全な代替になりますか?
host-level damage に対しては、ほぼそうです。container backend が active のとき approval が bypass されるのはそのためです。ただし、credential filtering や MCP boundaries の代替には なりません。
YOLO mode は実際に何を disable しますか?
current session における dangerous command approval prompts です。Tirith、container isolation、gateway authorization、env filtering は disable しません。
どの env vars を MCP subprocesses が見られるか、どう分かりますか?
PATH、HOME、USER、LANG、LC_ALL、TERM、SHELL、TMPDIR、XDG_*、そして server の explicit env block にあるものだけです。それ以外は stripped されます。
これを代わりに処理してくれる managed Hermes はありますか?
one-click deployments を提供する providers はあります。彼らが処理するのは install です。誰があなたの bot と話せるのか、MCP servers が何を読めるのかという trust decisions までは代わりに決めてくれません。それは、引き続きあなたの判断です。
自分の setup にもっと時間を使ったら、この話題にはまた戻ってきます。今のところ、私の理解はここまでです。
Previous Posts:
- 複数の scheduled tasks を設定しているなら、cron jobs に Hermes Cron Memory & Context Limits がどう影響するかを先に見ておくとよさそうです。
- overlapping runs や slow execution を troubleshooting しているなら、こちらの guide も参考になります:Safe Hermes MCP Setup for Cron Jobs。
- clear prompts と instructions で agent behavior を改善する話を深掘りするなら:How to Write Effective Hermes Agent Skills
- real-time monitoring の自動化を考えていますか?この guide が役に立ちます:Periodic Health Check Cron Jobs with Hermes
- cron delivery を optimize して stable results を得たい場合はこちら:Managing Agent Capabilities and Tool Access




