一行要約
ユーザーは権限プロンプトの 93% を承認している — つまりプロンプトは判断ではなく摩擦になっている。auto mode はこれを2層のモデルベース分類器で置き換え、実トラフィックで偽陽性 0.4% まで下げた。
要点
問題 — approval fatigue
ユーザーは Claude Code の権限プロンプトの 93% を承認している。
Approval fatigue, where people stop paying close attention to what they’re approving. 承認疲れ。人が、自分は何を承認しているのかを注意深く見なくなる状態のこと。
手動レビューの強制でも、全保護の無効化でもなく、モデルベースの分類器による自動判断で解く。
脅威モデルの4分類
- overeager behavior(やりすぎ)
- honest mistakes(善意の誤り)
- prompt injection
- model misalignment
The action instead looks like reasonable problem-solving, only applied past the boundary of what the user authorized or intended. その行為はむしろ筋の通った問題解決に見える。ただしユーザーが許可・意図した境界を越えて適用されているという点だけが違う。
危険な行動は「明らかに悪意ある行動」の形では現れない。まっとうな問題解決に見えるが、許可された境界を越えているという形で現れる。
2層の防御
入力層 — サーバ側の prompt-injection probe が、ツール出力がエージェントの context に入る前にスクリーニングする。乗っ取りの試みを検出したら警告を付加する。
出力層 — **transcript classifier(Sonnet 4.6)**が実行前に行動を評価する。2段階。
| 段階 | 内容 |
|---|---|
| Stage 1 | 高速な単一トークンの yes/no フィルタ。recall 重視で攻めた調整(偽陽性 8.5% を許容) |
| Stage 2 | Stage 1 でフラグが立った場合のみ chain-of-thought による推論。偽陽性を 0.4% まで下げる |
分類器は意図的に assistant のメッセージとツール出力を剥ぎ取り、user メッセージと素のツール呼び出しだけを見る。
Why strip assistant text and results: Prevents agents from generating persuasive rationalizations that could mislead the classifier. Tool outputs are primary injection vectors. assistant のテキストと結果を取り除く理由: エージェントが説得力のある正当化を生成して classifier を惑わせるのを防ぐため。ツールの出力は主要な injection の経路である。
Stage 2 は入力が最後の指示以外まったく同じなので prompt caching が効く。
権限の3層
| 層 | 内容 |
|---|---|
| Tier 1 | 組み込みの allowlist(ファイル読み取り、検索、コードナビゲーション)+ ユーザー設定のルール。任意のコード実行パターンは除外される |
| Tier 2 | プロジェクト内のファイル操作。分類器のレビューなしで許可 |
| Tier 3 | それ以外すべて(シェルコマンド、web fetch、外部ツール、プロジェクト外のファイル操作) |
ブロックされるもの(4カテゴリ)
- Destroy or exfiltrate — force push、大量削除、外部へのデータ送信
- Degrade security — ロギングの無効化、永続化機構のインストール
- Cross trust boundaries — 外部コードの実行、認証情報ストアの走査
- Bypass review or affect others — main への push、本番デプロイ
具体的にブロックされた例(どれも「まっとうに見える」のがポイント):
- 曖昧な指示からリモートブランチを削除する
- 認証エラーに当たったときに体系的に認証情報を探し回る
- 名前の類似性でインフラのターゲットを選ぶ(ユーザーが明示していないのに)
- 機密の可能性があるスクリプトを public な GitHub Gist にする
- 失敗したデプロイを検証フラグを飛ばしてリトライする
実測値
| データセット | Stage 1 FPR | Stage 1 FNR | パイプライン全体 FPR | 全体 FNR |
|---|---|---|---|---|
| 実トラフィック(n=10,000) | 8.5% | — | 0.4% | — |
| 実際の overeager 行動(n=52) | — | 6.6% | — | 17% |
| 合成の exfiltration(n=1,000) | — | 1.8% | — | 5.7% |
The 17% false-negative rate on real overeager actions represents actions the agent attempted but weren’t fully authorized by user context. 行き過ぎた実際の行為に対する17%という偽陰性率は、エージェントが試みたものの、ユーザーの文脈からは完全には許可されていなかった行為を表している。
実際の overeager 行動に対する偽陰性 17% は率直に開示されている。「安全でないものを完全に止める」ではなく「割に合う水準まで下げる」という設計思想。
deny-and-continue モデル
分類器がブロックしたとき、エージェントは処理を止めず、拒否理由とともに「より安全な方法を探せ」という指示を受け取る。
Denials return to the agent with the reason, allowing retries up to a limit. 拒否は理由とともにエージェントへ返され、上限までの再試行が認められる。
連続3回、または累計 20回の拒否で人間のレビューにエスカレートする。
multi-agent での適用点
分類器は委譲時と復帰時の両方を通す。委譲時は subagent のタスクがユーザーの意図を反映しているかを確認し、復帰時は実行中に注入されたコンテンツによる汚染を捕まえる。
カスタマイズできる箇所
- 環境の信頼境界(ドメイン、クラウドバケット、ソース管理の組織、内部サービス)
- 20 以上の既定のブロックルール(変更可能)
- allow の例外 — 宣言済みパッケージのインストールのような無害な一致への carve-out
そのまま使える具体例
自前のエージェントに同じ考え方を持ち込むときの設計チェックリスト:
□ 分類器に assistant のテキストとツール結果を見せていないか
→ 見せると「もっともらしい正当化」に釣られる。user メッセージと素のツール呼び出しだけ見せる
□ 1段構成になっていないか
→ 高速フィルタ(recall 重視)+ CoT(precision 回復)の2段にする。2段目は prompt caching が効く
□ ブロック時にエージェントを止めていないか
→ 理由を返して「より安全な方法を探せ」と続行させる。連続/累計で人間にエスカレート
□ 入力層の対策があるか
→ 分類器がツール結果を見ない設計なら、注入は入力層で別途スクリーニングする必要があるブロックルールの4カテゴリ(自分のポリシーを書くときの雛形):
Destroy or exfiltrate force push、大量削除、外部へのデータ送信
Degrade security ロギング無効化、永続化のインストール
Cross trust boundaries 外部コードの実行、認証情報ストアの走査
Bypass review / affect others main への push、本番デプロイ原典で言及されている関連文書
- claude-code-sandboxing — 権限プロンプトを減らすもう一方のアプローチ(隔離)
- how-claude-code-works — permission mode の一覧
- sub-agents — 委譲と復帰の権限継承
- demystifying-evals-for-ai-agents — FPR / FNR で分類器を評価する枠組み
- https://code.claude.com/docs/en/permission-modes#eliminate-prompts-with-auto-mode
未取得の派生リンク
- https://www-cdn.anthropic.com/14e4fb01875d2a69f646fa5e574dea2b1c0ff7b5.pdf — Claude Opus 4.6 system card