🛠️

Claude Codeの安全設計、Pythonスクリプト3本を捨ててdeny rulesに一本化した判断

に公開

「設定が3箇所に散らばっている」問題

Claude Codeで安全設計を組んでいると、こんな状態になりがちだ。

  • settings.jsonのdenyリストに静的パターンを追加
  • PreToolUse Hookに動的チェック用のPythonスクリプトを登録
  • auto-approve用のスクリプトで安全なコマンドの承認ダイアログをスキップ

自分の環境では、protect-branches.py(refspec解析で保護ブランチへのpushをブロック)、auto-approve-git-safe.py(安全なgitコマンドの自動承認)、auto-approve-gh-mcp.py(gh MCPツールの安全判定)の3本、合計200行超のPythonスクリプトがPreToolUseに登録されていた。

事故はゼロ。ちゃんと動いていた。でも、新しい保護パターンを追加するたびに「denyリストに追加すればいいのか、Pythonにも手を入れるべきか」を毎回判断する必要があり、設定の一覧性が悪い。

deny rulesのワイルドカードで十分だった

結論として、3本のPythonスクリプトを全削除し、permissions.denyのワイルドカードパターンだけで安全設計を完結させた。

たとえばprotect-branches.pyが80行かけてやっていたrefspec解析は、これで代替できる。

"Bash(git push *:main)",
"Bash(git push *:master)",
"Bash(git push *:dev)",
"Bash(git push *:refs/heads/main)",
"Bash(git push *:refs/heads/dev)"

*:mainのワイルドカードが「任意のローカルブランチからmainにpushする」パターンを全てキャッチする。git push feature:maingit push +HEAD:refs/heads/mainも引っかかる。

force pushも同様に網羅できる。

"Bash(git push --force:*)",
"Bash(git push -f:*)",
"Bash(git push --force-with-lease origin HEAD:refs/heads/main)"

なぜこれで十分と判断したか

Pythonスクリプトには「コマンド文字列を動的に解析して判定する」柔軟性があるが、実際に運用してみると、ブロックしたいパターンはほぼ全て文字列のパターンマッチで表現できるものだった。

方法 メリット デメリット
deny rulesワイルドカード 設定1ファイル完結、メンテ容易、依存なし 動的な判定は不可能
PreToolUse + Python 動的解析可能、外部API連携可能 設定分散、Python依存、デバッグ箇所が増える

判断の分岐点は「外部APIの呼び出しやランタイム情報が必要かどうか」。パターンマッチで済む操作のブロックにPythonを使うのは、オーバーエンジニアリングだった。

auto-approveスクリプトも不要になった理由

permissions.allow"Bash"を含めると、Bashコマンドはデフォルトで許可される。危険なコマンドだけpermissions.denyでブロックすればいい。

"permissions": {
  "allow": ["Bash", "Read", "Write", "Edit", "MultiEdit", ...],
  "deny": ["... 危険なパターンだけを列挙 ..."]
}

「denyが常にallowより優先される」という仕様を活かして、allowは広く取り、denyで穴を塞ぐ。この設計なら、auto-approve用Hookの出番はない。

Hooksを全廃したわけではない

PreToolUseの3スクリプトは消したが、Hooks自体は使い続けている。

  • SessionStart: コンテキスト圧縮後のリマインダー、ゾンビプロセス自動kill
  • PostToolUse: メモリ使用量モニタリング

「ブロック/許可」はdeny rules、「通知/監視/初期化」はHooks。守備範囲が違う。deny rulesで「イベント通知」はできないし、Hooksで「静的パターンのブロック」をやるのは冗長。

まとめ: 自分はこう判断している

安全設計で迷ったら、まずdeny rulesのワイルドカードで表現できないかを考える。パターンマッチで済むなら、Pythonスクリプトを書く必要はない。

Hooksが必要になるのは「外部API呼び出し」「ランタイム情報に基づく判定」「イベント通知・監視」の3パターンだけ。それ以外のブロック処理をHooksに書いているなら、deny rulesへの移行を検討する価値がある。


元記事

この記事は 【Claude Code 安全設計】HooksからPermissionsへ — 3つのPythonスクリプトを捨てた理由と移行ガイド のコア部分を再構成したものです。元記事ではさらに:

  • Before/After の設定差分と実際のコミット履歴(段階的移行の4コミット)
  • 移行判断フローチャートとチェックリスト
  • force push・ブランチ削除など全deny rulesパターンの網羅的な解説

を扱っています。


この記事は playpark Blog からの転載です。

Discussion