TL;DR
- 1 回ずつは無害な tool call でも、積み重ねると攻撃になります。Anthropic は、攻撃者が作業を「小さく、一見無害なタスク」に分けて Claude Code に実行させた事案を公表しました。数値は同社の自己公表です(Anthropic)。
- 既存の権限設計・ガードレール・egress 制御は、どれも 1 回の呼び出し を単位に判定します。この記事では、判定の単位を task → workflow → campaign の 3 階層に分けて整理しました(この記事の整理で、標準用語ではありません)。
- 認可は workflow に置き(宣言した目的と tool 列を照合する)、監査は campaign に置きます(identity・対象資産・時間窓で session を跨いで束ねる)。
- このリポジトリで測ったところ、hook は 2 本とも 1 回の呼び出しだけを見て判定していました。
session_idを参照するファイルは 0 件、呼び出しを跨いで状態を残す処理も 0 件です(refac4805e3、社内データ)。
はじめに:1 回ずつは無害な依頼が、合わせると攻撃になる
こんにちは、みねです。
この記事は「1 回ずつは無害な tool call の積み重ねを、どう認可・監査すればよいか」に答えます。
Anthropic は 2025 年 11 月、AI を使った諜報キャンペーンを検知・妨害したと公表しました(Anthropic)。同社の説明では、攻撃者は作業を小さな一見無害なタスクに分け、Claude には全体の悪意ある目的を見せませんでした。正当なセキュリティ企業の防御テストだと名乗ってもいます。標的は約 30、作業の 80〜90% を AI が実行し、人の判断点は 1 キャンペーンあたり 4〜6 か所だったとされます。いずれも Anthropic の自己公表で、第三者の検証は確認できていません。
この事案で大事なのは、個々の依頼が単体では審査を通る形をしていたことです。1 回ごとの判定をどれだけ厳しくしても、目的が分割されていれば各回は通ります。
既存記事との関係を先に書いておきます。
| 記事 | 判定の単位 | この記事が足すもの |
|---|---|---|
| AIコーディングセキュリティ設計 | 権限・流出・実行時・設計判断の 4 層 | 時間軸で束ねる単位 |
| AIエージェントの権限は影響範囲で設計する | 1 操作の被害半径 | 合成された被害半径 |
| LLMガードレール設計 | 1 往復の入出力 | 断片を結び付ける層 |
| Agent Sandboxの外向き通信をどこまで許すか | ネットワーク境界 | 境界内の正当な通信の積み重ね |
| 攻撃面としての長期記憶 | session を跨ぐ記憶の持ち越し | session を跨ぐ相関監査 |
1. task / workflow / campaign の 3 階層を定義する
この記事では次の 3 階層を使います。繰り返しになりますが、これは筆者の整理です。
| 階層 | 定義 | 例 | 判定で見るもの |
|---|---|---|---|
| task | 1 回の tool call | curl を 1 回打つ、ファイルを 1 つ読む | コマンド、引数、宛先 |
| workflow | 1 つの目的のために束ねた tool call の列 | 「依存ライブラリを更新して PR を作る」 | 宣言した目的と、実際の tool 列が合っているか |
| campaign | 複数の workflow・session に散った同じ目的の活動 | 数日かけて偵察・認証情報の収集・持ち出しを別々の session で行う | 同じ identity や対象資産に向かう活動の総和 |
OWASP の Top 10 for Agentic Applications 2026 は、リスクを ASI01〜ASI10 に分けています(OWASP GenAI Security Project)。このうち ASI02「Tool Misuse and Exploitation」と ASI08「Cascading Failures」は、項目名から見て、1 回の呼び出しに閉じず時間や主体を跨いで広がる問題としても読めます(筆者の解釈。原典が分割攻撃を扱っているという意味ではありません)。この記事の 3 階層は、これらを「どの単位で判定するか」の軸に並べ直す試みです。項目の詳しい中身は原典を確認してください。
2. 単発の検査が分割攻撃に負ける理由
FragBench(2026 年 5 月、arXiv)は、実際の 24 件のサイバー事案キャンペーンをもとに、悪意ある目的を一見無害な断片に分け、別々の session に散らしたベンチマークです(arXiv:2605.11029)。著者らは、単発の安全判定はこのコーパスでほぼ偶然水準だったと報告しています。session 横断のやり取りをグラフとして扱う検知器では、イベント単位の F1 が 0.88〜0.96 でした。いずれも著者の自己報告で、筆者は再現していません。
理由は単純です。単発の判定器が見られるのは、その 1 回の入力だけです。「この IP 帯のポートを調べる」「このファイルの形式を解析する」「この宛先へ送る」は、どれも単体なら正当な作業として説明がつきます。悪意はそれぞれの断片ではなく、断片の 並び にあります。
安全なモデルを組み合わせると、単体では作れない悪用が成立するという研究もあります(arXiv:2406.14595)。「部品が安全なら全体も安全」という前提は、エージェントでは成り立ちません。
3. 認可の置き場所:workflow-level authorization
task 単位の allow / deny は残します。そのうえで、workflow の単位にもう 1 つ認可を置きます。
考え方は、workflow の開始時に目的を宣言させ、実行中の tool 列が宣言から外れたら止める ことです。
# 擬似コード(この記事の設計。実在するスクリプトではない)
workflow を開始する:
declared = {目的, 触ってよい対象資産, 使ってよい tool の種類, 期限}
人または上位の方針が declared を承認する
各 tool call の前に:
task 単位の allow / deny を判定する # 既存の層
call の対象資産が declared.対象資産 に入るか
call の tool が declared.tool の種類 に入るか
外れたら: 止めて、workflow を宣言し直すよう求める
ポイントは 2 つです。
- 宣言は人が読める粒度にする。 「リポジトリ X の依存を更新して PR を作る。外部への送信は package registry だけ」のように書きます。これより細かいと人が承認できず、粗いと照合の意味がありません。
- 外れたら拒否ではなく「宣言し直し」に回す。 正当な作業も途中で目的が広がります。拒否にすると利用者は宣言を最初から広く書くようになり、照合が空洞化します。
4. session を跨ぐ相関監査:何をキーに束ねるか
workflow 単位の認可は、攻撃者が workflow 自体を分けてしまえば迂回されます。この種の事案に対応するのは campaign 単位の 監査 です。認可ではなく監査にするのは、session を跨ぐ判定を実行前に確定させるのが難しいからです。
束ねるキーの候補は 3 つです。
| キー | 何を束ねるか | 取り方の例 |
|---|---|---|
| identity | 同じ利用者・同じ API キー・同じ agent の活動 | 認証基盤のログ |
| 対象資産 | 同じホスト・同じリポジトリ・同じデータへのアクセス | tool call の引数 |
| 時間窓 | 一定期間内の活動 | タイムスタンプ |
Claude Code の hook には、すべてのイベントで共通の入力として session_id と transcript_path が渡されます(Claude Code Docs: Hooks)。session 内で束ねるだけなら、公式の入力だけで始められます。session を跨いで束ねるには、identity と対象資産のキーを自分で記録する必要があります。
# 擬似コード(この記事の設計。実在するスクリプトではない)
各 tool call の後に:
追記する {時刻, identity, session_id, tool, 対象資産, workflow の宣言 ID}
定期的に:
identity × 対象資産 × 時間窓 で束ねる
束の中の tool の並びを、既知の攻撃の段階(偵察 → 収集 → 持ち出し など)と照らす
一致した束を人のレビューに回す
多数の agent trace を横断して違反を探す研究として、Meerkat があります(arXiv:2604.11806)。著者らは、クラスタリングと agent による探索を組み合わせると、ベースラインの監視より違反を多く見つけられたと報告しています。campaign 単位の監査は、こうした「束ねてから見る」方向の延長にあります。
5. このリポジトリで測った:hook の判定単位はすべて単発だった
自分たちの設定がどの単位で判定しているかを数えました。
- 測定 ref:
ac4805e30b84cdbc44c813beafd6db8b03e23f04(取得日 2026-10-16) - 対象: コミットされた
.claude/settings.json、.claude/とscripts/配下のファイル。user / local / managed の設定は読んでいません
| 何を | 手段 | 値 |
|---|---|---|
| hook のイベント種別 | jq で .hooks のキーを列挙 | PreToolUse(matcher Bash)と PostToolUse(matcher Write|Edit|MultiEdit)の 2 本 |
session_id / transcript_path を参照するファイル | git grep -l | 0 件 |
| PreToolUse の hook がログや状態を書く処理 | tee / >> / log を grep | 0 件 |
PreToolUse の hook は呼び出しのたびに入力を読み、その 1 回だけで判定して終わります。前の呼び出しを覚える仕組みはありません。PostToolUse の hook は整形用で、セキュリティの判定はしていません。
つまりこのリポジトリの防御は、全部 task 単位です。分割された依頼が 1 回ずつ deny に当たらなければ、すべて通ります。これは設定の欠陥というより、判定の単位を設計していなかった結果です。
6. 検知の誤検出をどう扱うか
campaign 単位の監査は、必ず誤検出を出します。同じ利用者が同じリポジトリに何度もアクセスするのは、ほとんどの場合ただの通常業務です。
誤検出への対処として、筆者は次の順で考えています。
- 自動遮断しない。 campaign 単位の判定は確度が低いので、止めるのは workflow 単位の認可までにします。
- 人の判断点に回す。 束が怪しければ、その identity の次の workflow 宣言を人が承認する形に切り替えます。
- 宣言との差で絞る。 宣言した目的の範囲内で完結している束は優先度を下げます。宣言の外へ出た束を先に見ます。
Anthropic の公表でも、攻撃側には人の判断点が 4〜6 か所残っていたとされます。攻撃側の数字から防御側の設計を直接導くことはできませんが、防御側も判断を人に戻す点を設計に入れておく方が現実的だ、というのが筆者の解釈です。
7. この整理で言えないこと
- 3 階層は筆者の整理で、標準の用語ではありません。OWASP や MITRE の分類と 1 対 1 には対応しません。
- Anthropic の事案の数値は同社の、FragBench・Meerkat の数値は各著者の自己報告です。筆者はどれも再現していません。
- 擬似コードは設計の形を示したもので、このリポジトリに実装はありません。効果も測っていません。
- 測定はコミットされた設定だけが対象です。利用者ごとの設定や、製品側の監視は含みません。
まとめ
- 1 回ずつ無害な依頼は、単発の判定をすべて通ります。悪意は断片の並びにあります。
- task 単位の allow / deny は残し、workflow 単位の認可(目的の宣言と tool 列の照合)と campaign 単位の監査(identity・対象資産・時間窓での束ね)を足します。
- campaign 単位の判定は誤検出が出るので、自動遮断ではなく人の判断点に回します。
- まず自分の hook が何を単位に判定しているかを数えてください。このリポジトリでは全部 task 単位でした。
FAQ
1 回ごとの入出力ガードレールでは、分割された依頼を止められませんか
止めにくいと考えています。FragBench の著者は、無害に見える断片に分けた攻撃に対して単発の安全判定はほぼ偶然水準だったと自己報告しています。断片を session 横断で結び付ける層が別に要ります。
task・workflow・campaign の 3 階層は標準の用語ですか
標準ではなく、この記事の整理です。task は 1 回の tool call、workflow は 1 つの目的のために束ねた tool call の列、campaign は複数の workflow や session に散った同じ目的の活動を指します。
相関監査は何をキーに束ねればよいですか
この記事では identity・対象資産・時間窓の 3 つを候補にしています。Claude Code の hook には session_id が渡されるので、session 内の束ねは公式の入力だけで始められます。session を跨ぐ束ねは identity と対象資産で行います。
検知が誤検出だらけになりませんか
なります。そのため、この記事では閾値で自動遮断するのではなく、workflow を宣言し直す判断点に人を置く形を勧めています。Anthropic の公表では攻撃側の運用にも人の判断点が残っており、防御側も人に判断を戻す点を持つべきだというのは、そこからの筆者の解釈です。
References
- Anthropic「Disrupting the first reported AI-orchestrated cyber espionage campaign」 https://www.anthropic.com/news/disrupting-AI-espionage
- OWASP GenAI Security Project「OWASP Top 10 for Agentic Applications for 2026」(2025-12-09) https://genai.owasp.org/resource/owasp-top-10-for-agentic-applications-for-2026/
- Mehta et al.「FragBench: Cross-Session Attacks Hidden in Benign-Looking Fragments」 https://arxiv.org/abs/2605.11029
- Stein et al.「Detecting Safety Violations Across Many Agent Traces」 https://arxiv.org/abs/2604.11806
- Jones et al.「Adversaries Can Misuse Combinations of Safe Models」 https://arxiv.org/abs/2406.14595
- Claude Code Docs「Hooks reference」 https://code.claude.com/docs/en/hooks
