Claude Code に「やっちゃダメ」を教える — Security Hooks の設定
AI を自由に動かす時代のガードレール
Claude Code に auto mode が提供され始めて、AI にコマンド実行を任せる場面が増えてきました。サンドボックス内で AI を自由に動かして開発を加速させる、という使い方をしている人も多いと思います。
ただ、自由に動かすということは、指示の解釈を間違えて rm -rf / が走ったり、秘密鍵を読み取ろうとしたり、main に force push したりするリスクもあるということです。
せっかくの成果物が破損したり、セキュリティ上の問題が起きないように、hooks 機能 で多層防御をやっていきましょう。
3つの hooks を設定しよう
以下の3つを ~/.claude/hooks/ に作ります。
| hook | タイミング | やること |
|---|---|---|
| validate-bash.sh | コマンド実行前 (PreToolUse) | 危険パターンを検出してブロック |
| audit-log.sh | コマンド実行後 (PostToolUse) | 全コマンドをログに記録 |
| notify-sns.sh | ブロック時 / セッション終了時 | SNS 経由でメール通知 |
~/.claude/settings.json に登録します。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/validate-bash.sh"
}
]
}
],
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/audit-log.sh"
}
]
}
]
}
}
それぞれ見ていきましょう。
危険なコマンドをブロックしよう
validate-bash.sh で以下のパターンをブロックします。
- sudo: 権限昇格は全面禁止
- rm -rf /: ルートディレクトリへの再帰削除
- curl | bash: リモートスクリプトのパイプ実行
- dd, mkfs, fdisk: ディスク直接操作
- 秘密情報の読み取り:
.ssh/id_*,.aws/credentials,.gnupg/へのアクセス - chmod 777: 誰でもファイルを書き換えられる状態にするのは禁止
- git push —force main: main への force push
hooks の仕組みはシンプルです。stdin から JSON を受け取って、コマンド文字列を正規表現でチェックするだけ。
# sudo 系をブロック
if echo "$COMMAND" | grep -qEi '^\s*sudo\s'; then
echo "BLOCKED: sudo コマンドは禁止されています" >&2
exit 2 # exit 2 でブロック
fi
exit 0 なら許可、exit 2 ならブロック。これだけです。
ブロックされるとセッション上にエラーメッセージが表示されて、同時に SNS 経由でメール通知が飛ぶようにしています。
全コマンドを記録しよう
audit-log.sh で、実行されたすべてのコマンドをタイムスタンプ付きで記録しましょう。
echo "$(date -Iseconds) $CMD" >> ~/.claude/audit.log
ログはこんな感じで溜まっていきます。
2026-04-13T01:23:45+09:00 git status
2026-04-13T01:23:50+09:00 npm run build
2026-04-13T01:24:15+09:00 git add -A && git commit -m "..."
何か問題が起きたときに「何をやったか」を追跡できるので、入れておいて損はないです。
ブロック時にメール通知を飛ばそう
バックグラウンドで走っているエージェントがブロックされたケースは、画面を見ていないと気づけません。AWS SNS のトピックに publish して、メール通知が飛ぶようにしておきましょう。
バックグラウンドで送信するので、hook の応答速度には影響しません。
settings.json でも制限をかけよう
hooks とは別に、settings.json の permissions と sandbox でも制限をかけておきましょう。
{
"permissions": {
"deny": [
"Bash(rm -rf /)",
"Bash(sudo *)",
"Edit(~/.ssh/**)",
"Edit(~/.aws/credentials)",
"Read(~/.ssh/id_*)"
]
},
"sandbox": {
"enabled": true,
"filesystem": {
"denyWrite": ["~/.ssh", "~/.aws", "~/.gnupg", "/etc", "/var"],
"denyRead": ["~/.ssh/id_*", "~/.aws/credentials"]
}
}
}
hooks がコマンド内容ベースのブロック、permissions/sandbox がツール・ファイルパスベースのブロック。二重で防ぐのがポイントです。
実際に使ってみて
設定してから数ヶ月経ちますが、何度かブロックが発火しています。コミットメッセージにブロック対象のキーワードが含まれていて誤検知になったこともありますが、安全側に倒れるので問題ないです。パターンマッチが厳しすぎると感じたら、正規表現を調整すれば大丈夫です。
audit.log は地味に便利で、「さっきのセッションで何やったっけ」を振り返るのにも使えます。
AI にコマンド実行を任せるなら、こういうガードレールは早めに入れておきましょう。