一行要約

ユーザーは権限プロンプトの 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分類

  1. overeager behavior(やりすぎ)
  2. honest mistakes(善意の誤り)
  3. prompt injection
  4. 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 2Stage 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 FPRStage 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、本番デプロイ

原典で言及されている関連文書

未取得の派生リンク