自分のClaude Codeに入れている「危ないコマンドを止める番人」に、壊れた入力を3通り流してみたら、3通りのうち2通りで素通しだった。番人を作った本人の環境でも、止める仕組みが「止められなかったとき」にどう動くかは決めていなかった。
きっかけは10月のhooks関連の更新だった
10月14〜23日の更新で、hooksが「失敗したときに通すか止めるか」の扱いが何度か直されていた。
公式の変更履歴(changelog)を読むと、hooks(ツールを使う前後に自動で走る小さなプログラム)まわりで次の記載があった。
- v2.1.299(10月14日):プラグインのhookが止める役目を持つ場面で、hookに渡せない・応答が返らないときは「通す」でなく拒否になった
- v2.1.309(10月22日):PowerShell上のhookが終了コード2で終わっても止まらない問題を修正
- v2.1.310(10月23日):WindowsでGit Bashが無いとき、PreToolUse(ツール実行前に走るhook)がツール呼び出しを通してしまう問題を修正
在庫に入れていた「v2.1.295でhooksが失敗したら動作をブロックできるように」という情報は、今回読めた範囲のchangelogでは確認できなかった(295〜298の記載は読めていない)。この記事では確認できた3件だけを使う。
共通しているのは、「止める仕組みが壊れたとき、通すのか止めるのか」が、ツール側でも繰り返し直されている点だった。自分のhooksはどうなっているか、気になって調べた。
自分のhooksを数えたら26個、止められるのは2つだけだった
settings.jsonに26個のhookが入っていたが、実際に「止める」役目を持つのは2つだけだった。
settings.json(Claude Codeの設定ファイル)を開いて数えた結果は次のとおり。
- hookの総数:26個(15種類のタイミングに分散)
- 通知アプリへの連絡用:大半。末尾が「終了コード0で抜ける」書き方で、失敗しても必ず「通す」作りにしてある
- 止める役目:2つ(Bashコマンドの番人 bash-guard.sh と、返答の最後にリンク切れを調べる link-check.py)
通知用が「必ず通す」なのは意図どおりで、通知が失敗して作業が止まっては困る。問題は、止める役目の2つが壊れたときにも通す作りになっていないかだった。
fail openは「番人が壊れたら通す」、fail closedは「番人が壊れたら止める」。通知は前者、危険コマンドの番人は後者が向いている。
番人に壊れた入力を流したら、3通り中2通りが素通しだった
正常な入力では止まったが、壊れたJSONと、jqという部品が見つからない状態では、どちらも終了コード0(通す)を返した。
bash-guard.shは、Claude Codeから受け取ったJSONをjq(JSONから値を取り出すコマンド)で読み、コマンド文字列を取り出して危険な書き方に当たらないか調べる。取り出せなかったときの行は 「コマンド文字列が空なら終了コード0で抜ける」という1行 で、つまり「読めなければ通す」。危険な強制プッシュを模した文字列で試した。
- 正常な入力+危険コマンド:終了コード2(ブロック)
- 正常な入力+無害なコマンド(ls):終了コード0(通す)
- 壊れたJSON+危険コマンド:終了コード0(素通し)
- jqの場所を存在しないパスに差し替え+危険コマンド:終了コード0(素通し)
番人は「読めた入力」には強かった。一方で「読めなかった入力」は丸ごと通していた。macOSに入っているjqに頼っているので、更新で場所が変わった日に番人は黙って役目を終える。
ちなみに最初のテストは、番人自身に止められた。テスト用のコマンド文字列に危険な書き方をそのまま入れたため、実行前に番人が反応した。正常なときの番人は、ちゃんと働いている。
今回は動作確認だけで、bash-guard.shは書き換えていない。直すと、jqが入っていない環境でも作業が全部止まる副作用がある。止めるのか通すのかは、このあと決める。
今日からできること:番人の「壊れたとき」を一度だけ試す
自分の止める役目のhookに、壊れた入力を1回流して、終了コードを見るだけでいい。
止める役目のhookを入れている人は、Claude Codeに次のように頼むと、手順を代わりに実行してくれる。
settings.json の hooks のうち、ツールの実行を止める役目のもの(PreToolUse、PermissionRequest、UserPromptSubmit、Stop)を一覧にして。それぞれについて、①壊れたJSONを渡した場合 ②中で使っているコマンド(jqなど)が見つからない場合に、終了コードが0(通す)か2(止める)かを実際に流して確認し、表にして。ファイルの書き換えはしないで。
表を見て、「通す」になっていた行が危険コマンドの番人なら、そこだけ直す候補になる。通知用なら、そのままでいい。
