Hermes Agentの依存関係をOSVで監査する|130件を実機検査

Hermes Agentの依存関係をOSVで監査する|130件を実機検査

安全設定を増やしても、足元の依存パッケージには既知の脆弱性も残ります。2026 年 9 月 14 日、手元の Hermes Agent をsecurity auditへ通しました。130 コンポーネントから 14 件の finding が返りました。

Found 14 known vulnerability finding(s) across 130 component(s):

私は AI エージェントの安全を、プロンプトだけでは守りません。資格情報、実行権限、依存関係を別々に検査します。今回は OSV.dev を使う依存関係の検査に絞り、通常表示、JSON、CI 向け終了コードまで実機で確かめます。

前回の拒否線から、実行コードの来歴へ進む

前回の「Hermes Agentのdenyルールでforce pushを止める」では、危険なコマンドを実行前に止めました。今回は、許可した Hermes Agent 自身が読み込む Python package、plugin、MCP server を調べます。

時点確認できること
前回完了時approvals.denyで特定のterminal commandを拒否できます
今回開始時実行を許したpackageに既知の脆弱性があるかは分かりません
今回完了後OSVのfindingを人向け表示とJSONで読み、severityを終了コードへ変換できます

すでにhermes security auditを定期実行している場合は、「JSON を機械判定へ渡す」まで飛ばせます。

なぜAIエージェントに依存関係監査が要るのか

Hermes Agent は会話するだけの program ではありません。terminal、browser、MCP、messaging gateway を通じて外部へ接続します。依存 package の弱点は、入力処理、network 通信、credential の境界へ影響する場合があります。

一方、監査結果に脆弱性 ID が出たからといって、すぐ侵害されたとは限りません。対象機能を使っているか、攻撃条件が成立するか、修正版へ更新できるかを分けて判断します。

私なら、finding を隠すより先に記録します。ただし、件数だけで危険度を決めません。同じ問題が GHSA ID と PYSEC ID の両方で現れる場合もあるためです。

用語を揃える

用語今回の意味
OSVpackage名とversionから既知の脆弱性を検索できる公開databaseです
component監査対象になったpackageまたはserverの1単位です
findingOSV照合で返った脆弱性記録です。同じ問題の別IDを含む場合があります
severitylowmoderatehighcriticalなどの深刻度です
venvHermes Agentが使うPython仮想環境です
pluginHermesへ機能を追加する拡張です。requirementsも監査対象になります
MCP serverModel Context Protocolで外部toolを提供するprocessです
--fail-on指定severity以上のfindingで終了コードを非0にするoptionです

監査範囲を先に見る

security auditは、OS 全体を調べる scanner ではありません。Hermes Agent が管理する範囲へ照準を合わせます。

                         ┌──────────────────┐
                         │ hermes security  │
                         │ audit            │
                         └────────┬─────────┘
                                  │ package名 + version
                  ┌───────────────┼───────────────┐
                  ▼               ▼               ▼
        ┌────────────────┐ ┌──────────────┐ ┌──────────────┐
        │ Hermes venv    │ │ plugin deps  │ │ pinned MCP   │
        │ installed PyPI │ │ requirements │ │ npx / uvx    │
        └────────┬───────┘ └──────┬───────┘ └──────┬───────┘
                 └────────────────┼─────────────────┘

                         ┌──────────────────┐
                         │ OSV.dev API      │
                         │ finding / fixed  │
                         │ version          │
                         └──────────────────┘

対象外もあります。global へ入れた package、browser extension、editor extension は、この command では調べません。container image や OS package には、それぞれ別の scanner が必要です。

commandの入口を実機で確かめる

検証環境は Hermes Agent v0.21.0 です。まず、version と option を読みました。

hermes --version
hermes security audit --help

version 表示は次のとおりでした。

Hermes Agent v0.21.0 (2026.8.31) · upstream baf7ceea · local 1068df60 (+1 carried commit)
Python: 3.11.15
OpenAI SDK: 2.24.0

監査には 4 つの実用的な option がありました。

--json
--fail-on {low,moderate,high,critical}
--skip-venv
--skip-plugins
--skip-mcp

--skip-*は調査範囲を切り分ける option です。全体検査では付けません。

130コンポーネントをOSVへ照合する

通常表示は 1 command です。

hermes security audit

手元では終了コード 0 で完了し、14 finding が出ました。デフォルトの failure 境界がcriticalであり、今回の結果に critical がなかったためです。

結果の主要部分を抜粋します。

Found 14 known vulnerability finding(s) across 130 component(s):

[venv]
  HIGH      httpcore2==2.7.0  GHSA-7mj9-2mp8-4m2p
           fixed in: 2.10.0
  HIGH      httpx2==2.7.0  GHSA-7mj9-2mp8-4m2p
           fixed in: 2.10.0
  HIGH      httpx2==2.7.0  GHSA-8xx6-hgc6-gc2m
           fixed in: 2.12.0
  MODERATE  PyNaCl==1.5.0  GHSA-mrfv-m5wm-5w6w
           fixed in: 2.5.0, 1.24.0, 1.6.2

3 件が HIGH、4 件が MODERATE、7 件が UNKNOWN でした。すべてvenv由来です。表示された package はhttpcore2httpx2PyNaClでした。

14 という数字は 14 種類の攻撃を意味しません。今回の一覧では、GHSA と PYSEC の ID が同じ summary や fixed version を指す行を含みます。まず ID、package、version、summary を読み、重複関係を確認します。

また、出力の fixed version は更新候補の手掛かりです。個別 package だけを無理に上げる前に、Hermes Agent 側の依存制約と release を確認します。managed install なら、先にhermes update --checkで本体更新を確認する方が安全です。

JSONを機械判定へ渡す

人が読む一覧と、automation が読む値は分けます。

hermes security audit --json

実行結果の先頭は次の構造でした。秘密の値は含まれていません。

{
  "total_components_scanned": 130,
  "finding_count": 14,
  "findings": [
    {
      "package": "httpcore2",
      "version": "2.7.0",
      "ecosystem": "PyPI",
      "source": "venv",
      "vuln_id": "GHSA-7mj9-2mp8-4m2p",
      "severity": "HIGH",
      "fixed_versions": ["2.10.0"]
    }
  ]
}

report 保存時は、標準出力と終了コードを両方残します。

hermes security audit --json > hermes-security-audit.json
python3 -m json.tool hermes-security-audit.json > /dev/null
printf 'json_check=%s\n' "$?"

Hermes 起動時に secret source の状態を標準出力へ表示する環境では、JSON の前に status 行も入ります。今回の環境でも status は先に出ました。表示はBitwarden Secrets Manager: applied 21 secretsです。pipeline では、出力が純粋な JSON か検査します。混在する場合は Hermes の version と起動設定を確認します。parse error を finding 0 件として扱ってはいけません。

HIGH以上を終了コード1にする

デフォルトの critical 基準では、今回の HIGH finding があっても終了コード 0 でした。CI で HIGH 以上を止めるなら、境界を明示します。

hermes security audit --fail-on high
printf 'exit=%s\n' "$?"

同じ 14 finding を表示した後、実測では非 0 になりました。

exit=1

この終了コードなら、shell、cron、GitHub Actions から判定できます。ただし、導入初日にいきなり全 job を止めると修正作業まで止まることがあります。最初は report を保存し、担当者と期限を決めます。その後、解消済みの基準を CI gate へ上げます。

私なら、critical は即時停止、high は当日調査、moderate は定期更新へ載せます。実際の優先度は、利用経路と外部公開範囲も見て決めます。

scopeを切って原因を確かめる

今回の finding が venv 由来かを確かめるため、venv だけを外しました。

hermes security audit --skip-venv --json
printf 'exit=%s\n' "$?"

結果は 0 component、0 finding でした。

{"total_components_scanned": 0, "finding_count": 0, "findings": []}
exit=0

この結果は「Hermes 全体に問題がない」という意味ではありません。今回の設定には、監査可能な pinned plugin 依存と MCP component がなかったことを示します。--skip-venvを付けたまま定期実行すると、主要な 130 component を見落とします。

切り分け option は原因調査に使い、日常の基準 run は scope を省かず実行します。

findingが出た後の順序

検出後に package 名だけを見て即時削除すると、Hermes Agent を壊す恐れがあります。次の順で扱います。

  1. vuln_idを OSV または GitHub Advisory で開きます。
  2. affected version と fixed version を確認します。
  3. 対象機能を使っているか調べます。
  4. Hermes Agent の更新で解消するか確認します。
  5. 隔離、機能停止、credential 縮小などの暫定策を決めます。
  6. 更新後に同じ command を再実行します。

pip install -U httpx2のような直接更新は、managed venv の整合性を崩す場合があります。Hermes 本体の release と依存宣言を優先します。修正版がまだ取り込まれていない場合は、公式 issue や advisory を追います。

よくあるエラー

症状主な原因対応
securityauditがありませんHermes Agentが古い版ですhermes --versionと公式更新手順を確認します
OSVへの接続で失敗しますDNS、proxy、egress制限がありますnetwork経路を確認し、0件として記録しません
findingがあるのにexit 0ですデフォルトの--fail-on critical未満ですCI基準を--fail-on highなどで明示します
JSON parse errorになりますstatus行などがJSONの前へ出ていますraw outputを保存し、混在行とversionを確認します
--skip-venvで0件になりました最大のscan範囲を除外しています切り分け後はoptionなしで再実行します
同じsummaryが複数ありますGHSAとPYSECなど別IDで登録されていますIDとaffected rangeを照合し、件数だけで判断しません
fixed versionへ上げたらHermesが動きませんmanaged依存を個別に変更しましたHermes本体のupdate経路と依存制約へ戻します
pluginやMCPが出てきませんunpinned commandや対象外形式です--helpと公式の監査対象を確認します

監査を更新作業から分離する

脆弱性 scan と自動 update を同じ job にすると、検出した瞬間に実行環境が変わります。再現性が落ち、rollback も難しくなります。

私は scan を read-only で走らせ、結果を保存します。更新は別の変更として行い、version、test、再 scan をそろえます。これなら「何を見つけたか」と「何を直したか」が混ざりません。

今回の実測では、130 component から 14 finding が返り、--fail-on highは終了コード 1 でした。venv を除外すると 0 component になりました。この差により、検出元を Hermes の Python 環境へ絞れます。

AI エージェントを長く動かすなら、権限を固めた日で終わりではありません。依存関係は更新され、advisory も後から増えます。安全性は設定値ではなく、同じ検査を繰り返せる運用で保ちます。

一次情報

出典確認した内容
Hermes Agent Securitydefense-in-depth、supply-chain advisory checking、監査範囲
Hermes Agent CLI Commandshermes security auditと各option
Hermes Agent公式repositorysource、release、更新元
OSV APIpackage version照合、batch query、脆弱性ID取得
OSV Schemavulnerability recordの項目とaffected range
GitHub Advisory DatabaseGHSA IDの公開advisory
この記事をシェア