0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「安全フックを入れたから大丈夫」ではない——rm -rf は止まるのに DROP TABLE は素通りした話

0
Last updated at Posted at 2026-07-17

Claude Code に安全のフックを入れた。それで安心していた。

正直に言う。私は非エンジニアだ。コードは書けない。だから「危ない操作を止めてくれる」と紹介された無料のツールを入れて、それで守られた気になっていた。入れた、イコール、全部止まる。そう思い込んでいた。

だが「入れた」と「実際に止まる」は別だ。相方のClaude(この記事の技術の部分を書く方)に、既定のインストールが本当は何を止めて何を素通りさせるのかを、一つずつ終了コードで確かめてもらった。結論は、少し怖い。rm -rf / は実行の手前で止まる。だが本番データベースの DROP TABLE は、既定では素通りした。

以下、実測の記録。伝聞ではなく、手元で流して終了コードを見た一次の結果だ。

既定で入るのは「中核の8個」だけ

npx cc-safe-setup を引数なしで実行すると、~/.claude/hooks/ に入るのは中核の8個のフックだ。パッケージのカタログ(scripts.json)を直接読んで確認した。

内訳は、破壊的なコマンドを止める destructive-guard、分岐への直接の push を止める branch-guard、編集後の構文を検査する syntax-check、文脈の窓を監視する context-monitor、コメントの混入で許可リストが壊れるのを防ぐ comment-strip、読み取りの操作を自動で承認する cd-git-allow.env の混入を止める secret-guard、セッションの死亡を知らせる api-error-alert。この8個。

ここで大事なのは、この8個に「本番データベースの全消しを止めるフック」が入っていないことだ。

destructive-guard が止めるもの、止めないもの

破壊的な操作の番人である destructive-guard の本体を読むと、止める対象はこうだ。危険なパスへの rm -rfgit reset --hardgit clean -fd、広いパターンでの find ... -delete、それに git checkout --force。ファイルとgitの破壊が中心だ(分岐への直接の push は別の番人 branch-guard が受け持つ)。

一方、SQL の DROPTRUNCATE、条件のない DELETE は、この番人の対象外だった。だから既定のインストールだけの状態で、AIが psql -c "DROP TABLE users" を投げても、番人は素通りさせる。

危険なコマンドを実行せずに確かめる方法

どうやって「実行せずに」確かめたか。フックは標準入力でコマンドの文字列を受け取り、危ないと判断したら終了コード2で止める仕組みだ。だからコマンドを実際に走らせず、文字列として渡して、返ってくる終了コードだけを見ればいい。

# 実行はされない。文字列として hook に渡し、終了コードだけ見る
echo '{"tool_input":{"command":"rm -rf /"}}' | bash ~/.claude/hooks/destructive-guard.sh; echo "exit=$?"
# → exit=2(止まった)

echo '{"tool_input":{"command":"psql -c \"DROP TABLE users\""}}' | bash ~/.claude/hooks/destructive-guard.sh; echo "exit=$?"
# → exit=0(素通り)

rm -rf /exit=2DROP TABLEexit=0。手元で流した実測がこれだった。本番を一度も触らずに、自分の環境で境界を確かめられる。

データベースの全消しまで止めるには

では DROP を止めたい時はどうするか。既定の8個ではなく、例集(800個以上ある)から名指しで足す。

npx cc-safe-setup --install-example block-database-wipe

これで DROP DATABASEmigrate:freshdb:resetTRUNCATE TABLE を終了コード2で止めるフックが入る。足した後にもう一度さっきの一行で流すと、今度は DROP TABLEexit=2 に変わる。ちなみにこのフックは無料だ。穴を埋めるのに課金はいらない。

正直な限界も書いておく。足しても、TABLE を省いた素の TRUNCATE はすり抜けた。フックは文字列を見る最善努力の網であって、完全な保証ではない。だから宣言的な設定(permissions.deny)と、実行の手前のフックと、運用のルールを重ねる前提で使う。

まとめ

「安全ツールを入れた」で安心しない。「何が実際に止まるか」を終了コードで確かめる。これが今回の学びだ。

既定のインストールは、ファイルとgitの破壊には効く。だがデータベースの全消しは、例集から一つ足すまで素通りする。入れた時点で全部守られていると思い込むのが、一番危ない。

この「実際に止まるか終了コードで確かめる」やり方で、別の実際の事故——環境変数が原因でホームディレクトリが消える事故(起票 #75859)——を同じように調べたところ、中核フックにもう一つ穴が見つかった。見つけて直すまでを別の記事にまとめた:「安全フックを入れたから rm 事故は防げる」と思っていたら、ホームディレクトリへの削除が素通りした話

  • 無料の安全フック本体: npx cc-safe-setup
  • この記事で使った検証は、危険なコマンドを一度も実行していない。フックに文字列を渡して終了コードを見ているだけだ。仕組みはMITで公開されているので、中身は自分で読める。

事故の型ごとに、何が起きて、設定と運用と復旧でどう止めるかをまとめた本も別に置いている。気になる人は著者の本の一覧から、価格と評価を見て選べる。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?