Claude Codeのauto mode分類器は何を止めているか
auto modeの分類器がhard_deny・soft_deny・allowの3層でツール呼び出しを判定する仕組みと、classifyAllShellが塞ぐ抜け穴、検出範囲が広がってきた経緯をまとめます。
Claude Codeのauto mode分類器は、ツール呼び出しをhard_deny・soft_deny・allowの3層ルールで評価します。既定で無条件に止めるルールは実質1つ(データ流出の防止)だけで、git reset --hardやterraform destroyのような破壊的操作はすべて「ユーザーが明確な意図を示せば通る」soft_deny側に分類されています。classifyAllShellを有効にすると、狭いallowルールが分類器を素通りしていた抜け穴も塞がります。
auto mode分類器とは
auto mode分類器は、Claude Codeがauto modeで動いているときにツール呼び出しごとの安全性を判定するモデルです。読み取り専用の操作と作業ディレクトリ内のファイル編集は分類器を経由せず自動承認され、それ以外の操作は分類器の判定を通ります。分類器がどのくらいの精度で危険な操作を見分けているかは、Anthropicが公開した技術ブログで数値付きで解説されており、実トラフィックでの偽陽性率0.4%・overeager事例での偽陰性率17%という結果が示されています。この設計の全体像はClaude Code auto modeの中身にまとめているので、本記事では触れません。ここで扱うのは、その分類器に対して運用者が書き換えられるルール層です。
hard_deny・soft_deny・allowの判定順序
分類器の内部では、4段階の優先順位でルールが評価されます。
| 段階 | 何が起きるか |
|---|---|
1. hard_deny | 何が起きるか無条件でブロック。ユーザーの意図もallowも効かない |
2. soft_deny | 何が起きるか原則ブロックだが、次の2段階で覆る余地がある |
3. allow | 何が起きるかsoft_denyへの例外として、該当操作を通す |
| 4. 明示的なユーザーの意図 | 何が起きるか残ったsoft_denyをユーザーの直近の発言が上書きする |
4番目の「明示的な意図」は、漠然とした依頼では発動しません。「リポジトリを整理して」という指示はforce pushを正当化しませんが、「このブランチをforce pushして」と名指しした場合は通ります。一般的な依頼と、行動を具体的に名指しした依頼を分けて扱う設計です。
hard_denyが無条件で止めているのは実質1つ
既定のhard_denyルールをカスタム設定なしで文字通り読むと、含まれているのはデータ流出を防ぐルール1つだけです。autoMode.hard_denyに"$defaults"を含めずに独自ルールだけを書くと、この既定ルールごと失われるとドキュメントは明記しています。
一方でgit reset --hard・git clean -fd・terraform destroyのような、直感的には「無条件で止めてほしい」破壊的操作はsoft_denyに分類されています。ユーザーが「このブランチをforce pushして」と名指しすれば通る設計です。「取り返しがつかない操作=hard_deny」ではありません。hard_denyが守っているのは、Claude自身の判断や巧妙な指示では絶対に譲れない一線(データを外部に持ち出させない)に限られていて、それ以外の破壊的操作は「文脈次第で正当な依頼もありうる」という前提でsoft_deny止まりに置かれています。
classifyAllShellは「せまいallowルールの抜け穴」を塞ぐ拡張
auto modeに入ると、Bash(*)のような広範な実行許可ルールは既定で無効化されます。ただしBash(npm test)のような狭いallowルールはそのまま生き残り、分類器を経由せずに実行されます。ここに抜け穴があります。ルールの接頭辞が想定していない引数やスクリプトパスが渡された場合でも、分類器はそのコマンドを一度も見ないまま通してしまう可能性がある、という問題です。
autoMode.classifyAllShellをtrueにすると、auto mode中はすべてのBash・PowerShell allowルールが一時停止し、シェルコマンドは例外なく分類器の判定を経由します。
{
"autoMode": {
"classifyAllShell": true
}
}引き換えになるのはレイテンシです。これまで即座に通っていたコマンドも分類器の応答待ちが挟まり、シェルコマンド1件ごとに分類器呼び出しが発生します。この設定はv2.1.193以降でのみ有効で、それより古いバージョンはキーを読み飛ばし、狭いallowルールをauto mode中もそのまま持ち越します。
検出範囲はどう広がってきたか
分類器そのものの設計は変わっていませんが、既定で止める対象カテゴリはversionを追うごとに広がっています。
| バージョン | 追加された内容 |
|---|---|
| v2.1.136 | 追加された内容hard_denyルール層を追加。ユーザーの意図やallowを問わず無条件でブロックする仕組みが導入 |
| v2.1.193 | 追加された内容classifyAllShellを追加。あわせて拒否理由をトランスクリプト・通知・/permissionsに記録する機能も追加 |
| v2.1.195 | 追加された内容機密データの保管場所、保護対象のIaCスコープ、社内パッケージレジストリ回避など、environment設定に連動する新カテゴリを追加 |
| v2.1.198 | 追加された内容一時ディレクトリのワイルドカード削除、PR・issue本文経由の機密情報流出などをブロック対象に追加 |
| v2.1.200 | 追加された内容セキュリティ関連のテスト・アサーション改変、Claudeが作っていないステートフルリソースの削除、リモートURLの無断変更をブロック対象に追加 |
| v2.1.203 | 追加された内容セッション履歴やSSHキーなど機密性が高いローカルファイルの内容が、コミット・PR・gist経由で外に出るケースをブロック対象に追加 |
| v2.1.205 | 追加された内容セッショントランスクリプトファイルへの書き込み、解決できないシェル変数を対象にしたrm -rfをブロック対象に追加 |
追加は一方向で、既存のカテゴリが緩められた例は見当たりません。裏を返せば、classifyAllShellを有効にしていない環境では、この表の多くがBashコマンドの「よくあるパターン」にしか適用されない設計のままだった、とも読めます。狭いallowルールの外側は最初から手厚くなる一方、内側の抜け穴はclassifyAllShellを自分で有効にしない限り残り続けます。
拒否理由の表示はなぜ定型文に戻ったのか
v2.1.193で、分類器が拒否した理由をトランスクリプト・通知・/permissionsの「最近の拒否」タブに記録する機能が加わりました。当初は分類器が理由を書き出す想定でした。
ところがv2.1.208以降、ほとんどのセッションで表示される拒否理由はBlocked by classifierという固定文言に変わっています。分類器は内部の重要度スコアで判定するだけで、理由の文章を書く工程を挟まなくなりました。一部のセッションでは引き続き短い説明を書くモデルが使われますが、どちらが動くかはClaude Code側が選び、ユーザーが設定で切り替えられるものではありません。
理由の一律化は、レイテンシとコストを抑える方向の割り切りです。判定のたびに説明文を生成させるより、スコアだけを返すほうが速く、呼び出し回数の多いclassifyAllShell環境では特に効いてきます。詳しい理由が欲しい場面では、/permissionsの「最近の拒否」タブからrキーを押すと、その操作を手動承認つきで再試行できます。
連続3回、または合計20回のブロックが起きると、auto modeは一時停止してプロンプトに戻ります。この閾値はユーザー側で変更できず、許可された操作を1回はさむと連続カウンタはリセットされます。
environmentは何を判断材料にしているか
hard_deny・soft_deny・allowとは別に、autoMode.environmentというフィールドがあります。これはルールそのものではなく、分類器が「社内」と「社外」を見分けるための文脈情報です。信頼する送信先(リポジトリ・クラウドバケット・内部ドメイン・社内サービス)を書いておかないと、正規の操作でも分類器は「外部への送信」として扱い、soft_denyの対象に含めてしまいます。
既定で信頼されているのは、作業ディレクトリとそのリポジトリに設定済みのリモートだけです。データ流出防止(hard_deny)や機密データの取り扱い(v2.1.195以降のsoft_deny)は、このenvironmentの記述量に判定の精度が左右されます。誤検知が続く場合、ルールそのものより先にenvironmentの記述が薄くないかを疑うのが定石です。組織名や利用中のクラウド、社内ドメインを自然文で書き足すだけで、判定の的中率は変わってきます。
hard_denyとsoft_denyを自分で書き換える
autoModeの4フィールド(environment・allow・soft_deny・hard_deny)はいずれも自然文のルールとして書きます。既定を保ったまま追加したい場合は、配列に"$defaults"という文字列を含めます。
{
"autoMode": {
"hard_deny": [
"$defaults",
"Never send repository contents to third-party code-review APIs"
]
}
}"$defaults"を書かずに配列を独自ルールだけで埋めると、その区分の既定ルールを丸ごと失います。soft_denyを独自ルールだけで上書きすると、force push・curl | bash・本番デプロイ・auto modeのバイパスといった既定の禁止事項すべてが消えるとドキュメントは警告しています。設定を保存したあとは、必ずclaude auto-mode configで実際に効いているルールを確認できます。
よくある質問
hard_denyのルールは自分で増やせますか
増やせます。autoMode.hard_denyの配列に"$defaults"と一緒に自分のルールを書けば、既定の1件に追加する形になります。"$defaults"を省くと既定ルールごと消える点に注意が必要です。
classifyAllShellを有効にすると、すべてのコマンドで確認が必要になりますか
いいえ。あくまでauto mode中に分類器を通すという意味で、確認プロンプトが増えるわけではありません。分類器が許可すればこれまでどおり自動で実行され、危険と判定されたものだけが手元に返ってきます。増えるのは分類器の呼び出し回数と、それに伴うレイテンシです。
soft_denyに一致する操作は絶対に実行されませんか
されません、というのは正確ではありません。ユーザーが対象操作を名指しして依頼すれば通ります。絶対に実行させたくない操作はsoft_denyではなくhard_deny、またはそもそも分類器を経由させないpermissions.denyで止める必要があります。
拒否された理由が「Blocked by classifier」としか出ないのはなぜですか
v2.1.208以降、ほとんどのセッションで分類器は理由の文章を生成せず、内部スコアだけで判定するようになったためです。一部のセッションでは理由を書くモデルが動きますが、どちらが使われるかは設定で選べません。
まとめ
auto mode分類器はhard_deny・soft_deny・allowの3層と、ユーザーの明示的な意図による最終上書きの計4段階で判定します。既定で無条件に止まるのはデータ流出を防ぐルール1つだけで、git reset --hardのような破壊的操作の多くはsoft_deny止まりです。classifyAllShellは狭いallowルールが分類器を素通りする抜け穴を塞ぎますが、レイテンシと引き換えになります。検出対象のカテゴリはv2.1.136のhard_deny追加以降、一貫して広がる方向で更新されており、拒否理由の表示だけは逆にv2.1.208で定型文へ簡略化されました。運用ルールを自分で書き換えたいときは"$defaults"を必ず含め、claude auto-mode configで効いているルールを確認するのが安全です。分類器そのものを経由させたくない場合の手動モードへの戻し方はClaude Codeの自動承認オフ、auto modeが既定になった経緯はauto mode既定化で確認したい設定にまとめています。個人・チーム・組織それぞれの推奨設定はClaude Codeセキュリティ・権限ガイドが扱っています。