Hermes分離モデルの仕組みを組む手順

Artificial Intelligence

拙作ブログから。

昨日、こんなブログを書きました。

無検閲モデルに潜むリスク:バックドアを仕込まれたAIモデルが機密情報を盗み出すまで

この中で、以下のようなことを私は強調してるんですね。

  • きちんと権限管理を行い、不用意にエージェントが重要リソースに触れないようにしましょう
  • サンドボックスをきちんと構成しましょう
  • ネットワークアクセスとコマンド実行を分離しましょう

で、一応私の環境、Hermesのtoolsを中心にやっていいことダメなことを一通り整理はしたんですが、「ネットワークアクセスとコマンド実行の分離」というのがあまりピンときてなくて、これはちゃんと実装できてませんで。そのため、langfuseの活用法を問うた際に頑張ってHermesさんがデモ環境を作ろうとし始めて教えてもない勝手なことを色々し始めました。

  • 教えてもない内部環境内にあるOpenAI互換APIをディスカバリーして探そうとした
  • langfuseの巨大なモックアップを建造しようとした

やっぱりこれでさらに肝を冷やしまして、再度ちゃんとやろうとSwift-1.5-Qwen3.8-Flash-Next環境に問い合わせをしながら設定をやり直しました。以下はモデルが回答した内容に私が追記を入れたものです。参考になれば幸いです。

設定手順ざっくり

前提:Hermes の分離モデルの仕組み

Hermes Agent では「コマンド実行」と「ネットワークアクセス」はもともと別経路に設計されています。

  • コマンド実行(terminal / execute_code / ファイルツール)
    → ターミナルバックエンドで決まる場所で実行される
  • ネットワークアクセス(web_search / web_extract / browser ツール)
    → Hermes 本体プロセス(ホスト側)で実行される。サンドボックスコンテナ内ではない

つまり「コマンド実行を Docker サンドボックスに閉じ込め、そのコンテナを –network=none にする」ことで、コマンド実行にはネットワークを与えず、ネットワークアクセスはエージェントの web/browser ツール経由(ホスト側)だけに限定する分離が実現できます。公式ドキュメントも「コンテナバックエンドでは危険コマンドチェックがスキップされる(コンテナ自体がセキュリティ境界)ため、コンテナイメージを厳しくロックダウンせよ」と明確に注意しています。∑(ノ∀`*)アチャー

手順 1:コマンド実行を Docker サンドボックスへ隔離(既に実装済みだった)

~/.hermes/config.yaml でターミナルバックエンドを docker にします(Tips ページ推奨の .env 方式は TERMINAL_ENV=docker)。

terminal:
  backend: docker
  docker_image: "nousresearch/hermes-sandbox:desktop"   # または任意のハードニング済みイメージ
  container_cpu: 1
  container_memory: 5120      # MB
  container_disk: 51200       # MB
  container_persistent: true  # セッション間でコンテナを再利用

公式ドキュメントによると、Docker バックエンドのコンテナは Hermes により自動でハードニングされます(tools/environments/docker.py の _BASE_SECURITY_ARGS にて仕込み済み):

  • –cap-drop ALL(全 Linux ケーパビリティ削除)+ DAC_OVERRIDE/CHOWN/FOWNER のみ追加
  • –security-opt no-new-privileges(特権昇格禁止)
  • –pids-limit 256(プロセス数制限)
  • –tmpfs /tmp:rw,nosuid,size=512m、–tmpfs /var/tmp:rw,noexec,nosuid,size=256m

この状態のコマンド実行はホストから隔離され、危険コマンドチェックはスキップされます(コンテナが境界)。

手順 2:サンドボックスのネットワークを遮断(追加設定必要)

terminal:
  backend: docker
  docker_network: false   # false = --network=none。コンテナの全ネットワーク egress を遮断

ドキュメントの明記事項:

docker_network: false は terminal・execute_code・ファイルツールが使う実行コンテナに適用される

既存のネットワーク付きコンテナが存在する状態で切り替えると、そのコンテナは削除され新しい ネットワーク使用不可能なコンテナが起動する(背景プロセスは失われる、警告ログあり)

docker_extra_args で --network=none を渡すより、この第一級キーを推奨(docker_extra_args は最後に追加され Hermes のデフォルトを上書きしうるため、サンドボックス強化と衝突するフラグは隔離を静かに弱める)

これで「コマンド実行=ネットワークなし」が確定します。

手順 3:ツールセットで制御(修正済み)

ネットワークアクセスは web / search / browser ツールセット経由でのみ許可します。セッションごとにツールを絞る:

# ネットワークツール + ファイルのみ、コマンド実行なしの構成例
hermes chat --toolsets web,file

# コマンド実行も web も必要な開発用途
hermes chat --toolsets debugging   # file + terminal + web の複合

# セッション内で動的に
/tools disable browser

ツールセット参照ページには「safe」セット(web_extract/web_search/vision_analyze/image_generate のみ=書き込み・terminal・コード実行なし)も定義されており、ネットワーク専用アクセスの最小構成に使えます。逆に、コマンド実行側(コンテナ)にはネットワークがないため、コンテナ内のコードが外部へ通信・情報流出することはできません。

このあたりは、私自身の環境では hermes tools コマンドにてツールの使用可能・不可能を設定しています。

手順 4:機密情報の分離(コンテナへの漏洩防止:実装済み)

terminal:
  backend: docker
  docker_network: false
  docker_forward_env: []        # 空 = シークレットをコンテナに転送しない(デフォルト)
  # docker_forward_env: ["GITHUB_TOKEN"]  # 必要時だけ明示。コンテナ内コードが読み出し exfiltrate 可能になる点に注意
  docker_volumes:
    - "/home/user/data:/data:ro"   # :ro で読み取り専用
  env_passthrough: []            # 明示的に許可した変数だけが terminal/execute_code に渡る

ドキュメントの警告:docker_forward_env に名前を加えた変数はコンテナ内に意図的に注入され、コンテナ内で動くコードがそれを読み取って外部へ送れるようになる(air-gap なら egress がないので流出経路は閉じる)。execute_code と terminal は子プロセスから KEY/TOKEN/SECRET/PASSWORD 等を含む環境変数をデフォルトでストリップします。

・・・・・・とありますが、当方の環境ではそもそもがそういう事を許容していません。そのうちarXiv論文などため込んだドキュメントファイルだけ読ませても良いかなーとは思っているんですが、今のところは完全にファイル環境は遮断状態で進めてます。

手順 5:ファイル書き込みサンドボックス

export HERMES_WRITE_SAFE_ROOT=/path/to/project:/home/you/.hermes

write_file / patch はこの接頭辞外への書き込みをハードブロック(承認経由不可)

公式 Docker イメージでは HERMES_WRITE_SAFE_ROOT=/opt/data が自動設定

保護パス(/.ssh/、/.aws/、~/.kube/、.env、Hermes のシークレットストア等)は safe root 外・内に関係なく常時ブロック

注意:terminal ツールは同じ OS ユーザーとして動くため shell 経由では書ける。書き込みガードは「事故低減」であり敵対エージェントに対する硬境界ではない、とドキュメントが明言 → だから手順 1?2 のコンテナ隔離が本丸

手順 6:承認層(コマンド実行の人間関与:追加実装しました)

approvals:
  mode: smart          # smart | manual | off(off は --yolo と同等。信頼環境のみ)
  timeout: 300
  cron_mode: deny      # 無人コンテキストは危険コマンドを即時拒否
  unattended_mode: deny
  deny:                # --yolo / mode:off より先に効くユーザー定義ブロックリスト
    - "git push --force*"
    - "*curl*|*sh*"
    - "dd if=* of=/dev/*"

固定の hardline blocklist(rm -rf /、fork bomb、mkfs、ブロックデバイス書き込み、URL を sh にパイプ 等)はいかなる設定でも実行されない メッセージングゲートウェイを使うなら、ユーザー認可も分離の一部:TELEGRAM_ALLOWED_USERS=… 等の許可リストを使い、GATEWAY_ALLOW_ALL_USERS=true を terminal 権限のあるボットに設定しない(Tips ページの明示的警告)

hermes上で動くエージェントは curl を多用しますんで、この設定は必須だと思っています。

手順 7(任意):コマンド実行にネットワークが必要な場合の選択的付与

air-gap を解く場合は、docker_extra_args で –network を明示的に制御します(例:制限付き egress プロキシを持つ専用 Docker ネットワークに接続)。ドキュメントの注意:このリストは docker run に最後に追加され Hermes デフォルトを上書きしうるため、–cap-drop・–user・workspace マウントと衝突するフラグは隔離を静かに弱める。使う際は「コマンド実行にネットワークを与える」意図を明示し、コンテナイメージとマウントをロックダウンした上で行う。

この内容は、現状ではair-gapを外してないので、実施はしていません。

まとめ(分離の全体像)

層設定効果
コマンド実行の隔離terminal.backend: docker全 shell 実行が cap-drop・no-new-privileges のコンテナへ
コマンド実行のネットワーク遮断terminal.docker_network: false–network=none で egress 完全遮断
ネットワークアクセスの限定web/browser ツールセットのみ許可通信はホスト側のエージェントツール経由のみ
機密分離docker_forward_env: []、:ro マウント認証情報がコンテナ内コードに届かない
書き込み隔離HERMES_WRITE_SAFE_ROOTファイルツール書き込み先を限定
承認層approvals.mode: smart + deny破壊的コマンドの human-in-the-loop、yolo より優先のブロック

コメント

タイトルとURLをコピーしました