私は Claude Code の安全フックを無料で配っている(cc-safe-setup)。危険な操作を実行の手前で止めるための小さなフックの集まりだ。だから、こういう報告が出た時は、他人事ではなく、自分の配布物を確かめる番だと受け取る。
報告はこうだ。PreToolUse のフックが「人に確認させる」判定(permissionDecision: "ask")を返しても、セッションが bypassPermissions(権限の確認を飛ばすモード)で動いていると、その確認は黙って自動で承認され、ツールがそのまま実行される。一方で「拒否」の判定(deny)は同じ状況でもちゃんと効く。
これは、危険な操作にだけ人の確認を挟みたい、という安全フックの一番大事な使い方を、静かに無効にする。画面には何も出ない。使う側は「確認を挟んだつもり」でいるのに、実際は素通りしている。
そこで私は、自分の配っている 910 個のフックを自分の環境で数え直し、どれが生き残ってどれが黙って通す側かを分けた。そして、数える途中で自分のコードに見つけた嘘のコメントを直した。以下はその記録だ。報告そのものは伝聞、数えた結果と直した箇所は手元の実測、として分けて書く。
報告の中身(伝聞)
出どころは GitHub の起票 #77212(2026-07-13・OPEN)だ。報告者は、permissions.defaultMode を bypassPermissions にした状態で、ask を返すフックと deny を返す姉妹のフックを同じセッションで走らせ、次を観測している。
-
askを返した側の対象は、確認のダイアログが一切出ずにそのまま実行された。 -
denyを返した側の対象は、同じセッションで正しくブロックされた。 - フック自体は動いていて、
askの JSON を出力していることも(同じ入力を手でフックに流して)確認済み、とある。
つまり、フックが「確認して」と言っても、bypassPermissions の下ではその声が届かず黙って通る、という報告だ。ここまでは報告者の観測なので伝聞として書いている。この起票は今も開いたままで、直したという告知は出ていない(この記事を書いた時点)。
起票には、別の安全フックの作者からの裏づけも付いている。ローカルの拒否フックを配っている維持者が、こう書いている——bypassPermissions で動く安全フックでは ask を強制の境界に使ってはいけない、うちのフックは硬い拒否(exit 2)を使うので確認のダイアログが尊重されるかどうかに依存しない、と。強制したいなら、まず拒否して、人の例外が要るなら別経路で許可を出す形が安全だ、という主張だ。
だから自分のフックを数え直した(手元の実測)
報告が本当なら、私の配布物のうち ask で人に確認させているフックは、bypassPermissions の下で黙って通ってしまう。起票はまだ開いたままで、直ったという告知も無い。だから自分の環境でも当てはまる。確かめる価値がある。
cc-safe-setup の実体(examples/ 配下)を自分の環境で数えた結果(2026年7月16日の時点)はこうだ。
- フックの総数: 910 個
- 強制に硬い拒否(
exit 2)を使うフック: 285 個。報告のとおりdenyはbypassPermissionsでも効くので、この 285 個は生き残る。 -
permissionDecision: "deny"を明示で使うフック: 4 個。これも生き残る。 permissionDecision: "ask"を使うフックは 2 個。これが、bypassPermissionsの下で黙って通る側だった。
うちの安全網の大多数は硬い拒否で組んであり、取り返しの付かない破壊的な操作——rm -rf の連鎖、DROP TABLE、migrate:fresh、認証情報を漁る操作、子プロセスの暴走など——は、すべて exit 2 で止める。これらは bypassPermissions でも効く。ここは一安心だった。問題は、残る 2 個だ。
黙って通っていた 2 個の中身
一つ目は memory-write-guard.sh。Claude Code が記憶(CLAUDE.md や memory のファイル)を勝手に書き換えるのを、任意で確認できるフックだ。既定は記録だけ(off)で、利用者が CC_MEMORY_WRITE_APPROVAL=ask にした時だけ ask を返す。
ここで、自分のコードのコメントに嘘があった。ask を返す箇所に、こう書いてあったのだ——「対話でない時は、これが書き込みを止める(Claude Code は未承認として扱う)」。これは bypassPermissions の下では誤りだ。起票のとおり、そのモードでは ask は黙って承認されるので止まらない。過去の自分が、確かめずに「止まるはず」と書いていた。今回そのファイルを自分で確かめて、初めて気づいた。
二つ目は mcp-tool-guard.sh。MCP のツールが名前からは分からない破壊的な操作(たとえば自動操作で「削除」ボタンを押して本番のデータを消す)を、自動承認モードの下でエスカレートするフックだ。破壊的なツール名(delete/remove/drop など)や本番のホストへの操作は exit 2 と deny で硬く止める。だが、任意の設定(CC_MCP_AUTOMATION_GUARD=ask)にした時の「自動操作の確認」の枝が ask を返す。よりによって、この枝が発火する条件は「モードが bypassPermissions などの自動承認」の時——つまり ask が黙って通る、まさにその状況だった。自分自身を出し抜く形になっていた。
直した(責任を持って開示する)
見つけたので直した。挙動そのもの(ask の選択肢)は消さない——対話のセッションでは ask は正しく確認を出すし、それを求める使い方は妥当だからだ。直したのは「誤解を生む記述」だ。
-
memory-write-guard.sh: 嘘のコメントを、正確な記述に是正した。bypassPermissionsの下ではaskは黙って承認され書き込みは止まらない、強制したいならCC_MEMORY_WRITE_APPROVAL=block(exit 2)を使え、これは常に尊重される、と明記した。 -
mcp-tool-guard.sh:askの枝の直前に、同じ注意を足した。bypassPermissionsはaskを黙って自動承認するので、自動承認モードで硬く強制したいならCC_MCP_AUTOMATION_GUARD=block(exit 2)を使え、と。
どちらも block(exit 2)の選択肢は最初からあり、そちらは生き残る。だから利用者は、bypassPermissions で回すなら block を選べばよい、と分かる形にした。
公開の前にもう一度数えたら、直したはずの一つが巻き戻っていた
ここまでが7月16日の話だ。この記事を公開する前(7月26日)に、念のためもう一度数え直した。すると二つ、状況が変わっていた。
一つ。memory-write-guard.sh に入れたはずの正確な記述が、消えていた。是正の後、このフックは別の改修で書き直され、その書き直しが古いコメント——「対話でない時は、ask が書き込みを止める」という、まさに私が嘘だと確かめて消した記述——を復活させていた。直したはずの嘘が、10日で戻っていた。
二つ。ask を使うフックが 2 個から 3 個に増えていた。増えた 1 個は PowerShell の削除ガードで、Remove-Item -Recurse -Force の絶対パスへの実行に確認を挟む枝が ask を返す。よりによって、この確認が本当に欲しい場面の多く——無人の自動運用——は bypassPermissions で回っていて、そこでは確認は黙って承認される。
だから両方とも、その場で直した(今の実体は、総数 908 個・硬い拒否 284 個・ask 3 個で、3 個とも bypassPermissions では確認が出ないという注意を書き込んだ)。この再点検から言えるのは、一度直したことも、確かめ続けない限り正しいままではいない、ということだ。是正は改修の波に流される。フックの安全は在庫でなく、数え直す習慣のほうにある。
教訓——bypass モードでは、確認は助言、強制は硬い拒否だけ
まとめるとこうだ。
bypassPermissions(や --dangerously-skip-permissions)で回すなら、フックの「確認(ask)」は当てにできない。黙って通る。効くのは硬い拒否(exit 2、または deny)だけだ。だから、絶対に自動で走らせたくない操作は ask でなく exit 2 で止める設計にする。人の例外が要るなら、その場の確認ではなく、設定や環境変数のような別経路で明示の許可を出す。
そして——自分の配っているものや自分の設定を、報告が出たら実際に数え直す。「止まるはず」で書いたコメントは、確かめるまで正しいとは限らない。私自身、自分で確かめて初めて、2 個の穴と 1 個の嘘のコメントに気づいた。
自分のフックを確かめる
同じことを、あなたのフックでもできる。フックのディレクトリで、強制の仕方を数えてみるといい。
# 硬い拒否(bypassでも効く)を使うフック
grep -rl 'exit 2' ~/.claude/hooks/ .claude/hooks/ 2>/dev/null
# ask を返すフック(bypassPermissionsでは黙って通る = 過信しない)
grep -rl 'permissionDecision.*"ask"' ~/.claude/hooks/ .claude/hooks/ 2>/dev/null
ask を返すフックがあり、かつ bypassPermissions で回しているなら、そのフックは今、確認を出していない。強制したいなら、そのフックを exit 2 の拒否に変えるか、bypass モードをやめて既定のモードに戻す。
私が配っている安全フックの集まり cc-safe-setup は、この記事で数えたとおり、破壊的な操作は硬い拒否(exit 2)で止める設計だ。導入は次の一行で、MIT ライセンスの無料。
npx cc-safe-setup
そして、こうした「止まっているつもりで、実は黙って通っていた」という沈黙の失敗を含め、Claude Code で実際に起きた事故を「症状 → 検出 → 復旧 → 予防」の順にまとめた買い切りの本(Anthropic公式ガイドにない事故防止・¥800)も出している。無断の従量課金、副の作業者の暴走、設定が黙って元に戻る事故など、表示と実態がずれてお金やデータが静かに溶ける型を、複数の章で扱っている。第3章まで無料で試し読みでき、以降も月ごとに新しい事故を追記して、購入者には無償の更新で届く。