Claude Codeに秘密情報を扱わせないhooksの設定例|denyで防げない経路を止める(テンプレート公開)ARTICLE
ARTICLEAI開発
前の記事で、Claude Code の読み取り禁止(permissions.deny)を6つの経路で試した結果を書きました。ファイルを直接開く操作と cat などのコマンドは止まる一方、ファイル名を指定しない grep の全体検索、Python などのスクリプト経由の読み出し、source .env で環境変数に入れて使う経路は止まりませんでした。
この記事は、その続きです。deny で防げない経路を、Claude Code の hooks で塞ぐ設定例を解説します。設定一式は GitHub で公開しています。
- ks-rogers/claude-code-guardrails(MIT ライセンス)
この記事の要点
- hooks は、プロンプトの送信前やツールの実行前に、自分で書いたスクリプトを走らせて止める・確認する・記録する仕組みです。deny と同じく、リポジトリにコミットすれば全員に効きます
- 用意したのは3本です。①送信前に認証情報の形を検出して止める、②deny をすり抜ける読み出しや外部送信を実行前に確認する、③PR に「AI利用あり」がなければ止める
- 判定はパターン一致で、万能ではありません。行動ルールを書いた CLAUDE.md と、本番の認証情報を手元に置かない運用を組み合わせます
deny が止めるもの、hooks が受け持つもの
Claude Code には、ルールを扱う仕組みが3つあります。強さが違うので、行動ルールごとに使い分けます。
| 仕組み | 何をするか | 強さ |
|---|---|---|
| CLAUDE.md | 毎回のセッションで Claude が読む指示 | 促すだけ。指示次第で外れる |
permissions.deny | ファイルの読み取りやコマンドを機械的に止める | 強制。個人の設定で上書きできない |
| hooks | ツール実行の直前などに自作の判定を走らせ、止める・確認する・記録する | 強制。判定はパターン一致 |
前の記事の6つの経路に当てはめると、受け持ちは次のようになります。
| 経路 | 受け持ち |
|---|---|
Read ツールで開く、cat / head / tail / リダイレクト | deny(止める) |
grep -r での全体検索、スクリプト経由、source で環境変数に入れる、env の一覧表示、外部への送信 | hook ②(実行前に人の確認を求める) |
| プロンプトに認証情報を貼り付ける | hook ①(送信を止める) |
| AI が書いた PR に「AI利用あり」を書く | hook ③(なければ止める) |
| 人がファイルを開いてコピーし、貼り付ける | 行動ルール(CLAUDE.md) |
hooks の書き方
hooks は .claude/settings.json に登録します。どのタイミング(イベント)で、どのスクリプトを動かすかを書くだけです。
{
"hooks": {
"UserPromptSubmit": [
{ "hooks": [ { "type": "command", "command": "bash .claude/hooks/check-prompt-secrets.sh" } ] }
],
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "bash .claude/hooks/check-bash.sh" },
{ "type": "command", "command": "bash .claude/hooks/check-pr-ai-label.sh" }
]
}
]
}
}
UserPromptSubmit:ユーザーがプロンプトを送る直前。スクリプトには送る内容が JSON で渡されます。終了コード 2 で送信を止め、標準エラーに書いた文がユーザーに表示されますPreToolUse:ツールを実行する直前。matcherで対象のツール(ここでは Bash)を絞れます。スクリプトには実行しようとしているコマンドが JSON で渡され、JSON を返して「止める(deny)」「人に確認する(ask)」を指示できます
deny と同じく、この設定はリポジトリにコミットします。クローンした全員に同じ hooks がかかり、変更は通常の PR レビューを通ります。
hook ①:送信前に認証情報の形を検出して止める
プロンプトの中に、認証情報の形が含まれていたら送信を止めます。検出しているのは、たとえば次のような形です。
- AWS のアクセスキー(
AKIAで始まる20文字) - 秘密鍵(
-----BEGIN ... PRIVATE KEY-----) - GitHub・Slack・OpenAI・Google の各トークンや API キーの形
- JWT(
eyJ...が2つ続く形) password=、token:のように、鍵になる語のあとに8文字以上の値が続く形- パスワード入りの接続文字列(
mysql://user:pass@...など)
止めたときは、「認証情報は一部を伏せた形でも入力しない」「値を消すかダミーに置き換える」「本物を貼った場合はキーを無効化して報告する」という案内を表示します。
メールアドレスや電話番号の形は、止めずに警告だけにしています。顧客の業務データは、氏名・連絡先・IDを消し、件数を絞ったものだけ入力できる、という区分の運用を思い出してもらうためです。ここを止めてしまうと、テスト用のダミーデータまで扱えなくなります。
hook ②:deny をすり抜ける読み出しと外部送信を、実行前に確認する
Bash のコマンドを実行する前に、次のパターンを検出します。見つけたら止めるのではなく、人に確認を求めます。正当な用途もあるからです。
| 検出するもの | 例 |
|---|---|
| ファイル名を指定しない全体検索で、認証情報らしい語を探している | grep -rn PASSWORD . |
| 設定ファイルを環境変数に読み込む | source .env、set -a、--defaults-file= |
| スクリプト経由でファイルを開く | python3 -c "print(open('.env').read())" |
| 環境変数の一覧表示 | env、printenv |
| 外部への送信・共有 | curl -d、curl -X POST、gh gist、scp |
確認のダイアログには「秘密情報を読み出したり外部に送ったりしないことを確認してから許可してください」と理由が出ます。前の記事で「止まらない」と書いた3つの経路(全体検索、スクリプト経由、環境変数経由)は、これで少なくとも人の目を通るようになります。
hook ③:PR に「AI利用あり」がなければ止める
「AI が作成・変更したコードを含む PR は、人がレビューしてからマージする」というルールを回すには、まずどの PR に AI が関わったかが分かる必要があります。
この hook は、Claude が gh pr create で PR を作ろうとしたとき、本文に「AI利用あり」がなければ止めて、「本文の先頭に『AI利用あり:<AI が書いた範囲>』を足して再実行するように」と Claude に伝えます。Claude は本文を直して作り直します。人が手で作る PR には、同じ欄を持つ PR テンプレート(.github/pull_request_template.md)を用意しています。
止めた事象は記録する
3本の hook は、止めた・確認を求めた・警告した事象を、日時とパターンの種類つきで ~/.claude/ai-rules-hook.log に残します。これは監視のためではなく、判定を直すための記録です。導入して1〜2週間はこのログを見て、正当な操作まで止めている(誤検知)パターンを緩め、通したくないのに通った事例があればパターンを足します。
CLAUDE.md には「止められたときの振る舞い」を書く
hooks と deny は機械的に止めますが、Claude は止められると別の方法を探すことがあります。そこで CLAUDE.md に、秘密情報の3区分(認証情報・業務データ・コードと設計)と、次の一文を書いています。
hooks や deny で止まった操作は、無理に別の方法で実行しない。理由を伝えて、人に判断してもらう
CLAUDE.md は指示であって強制ではありませんが、「止まったら人に返す」という振る舞いを揃えておくと、hooks の効果が安定します。全文はリポジトリの CLAUDE.md にあります。
導入の手順
- リポジトリの
.claude/、CLAUDE.md(既存があれば末尾に追記)、.github/pull_request_template.mdを自分のリポジトリにコピーする chmod +x .claude/hooks/*.sh.claude/settings.jsonのdenyに、そのリポジトリ固有の実環境の設定ファイルを足す。判断の基準は、ファイルの種類ではなく書かれている値。テンプレートやダミー値だけのファイルは対象にしないCLAUDE.mdの報告先を埋める- PR を出してレビューを通し、マージ。各メンバーは
git pull後、次のセッションから有効 claudeを起動し、ダミーのキー(AKIAAAAAAAAAAAAAAAAA)を含む文を送って止まることを確かめる
複数のリポジトリを親ディレクトリにまとめて開いている場合は、前の記事で書いたとおり、親ディレクトリ側の設定に配下すべての deny と hooks をまとめて入れます。
防げないこと
- パターン一致の限界:見たことのない形の秘密情報や、巧妙な読み出し方は通ります
- 値を「見ずに使う」経路:
source .envしてから DB に接続するような操作は、確認を求めるだけで、許可されれば通ります - 人の行為:ファイルを開いてコピーし、チャットに貼る行為は防げません
- Claude Code 以外:Cursor・Codex・GitHub Copilot には効きません。それぞれの仕組み(
.cursorignore、.codex/config.toml、Content exclusion)で同じ対象を指定します - 起動オプション:メンバーが制限を緩めて起動することは、リポジトリの設定では防げません。組織全体で強制するには管理者設定を配ります
最も確実なのは、AI が読める場所に本番の認証情報を置かないことです。手元の開発環境ではダミーや開発用の値だけを使い、本番の認証情報はシークレット管理のサービスに置く。この設定は、その上に重ねる保険です。
K.S.Rogers の支援
K.S.Rogers では、自社の開発向けに作ったこの設定を公開しています。開発チームへの AI コーディングツールの導入、利用ルールと設定のひな形づくり、外注先に求める AI 利用ルールの整理(システム開発を外注するときのAI利用ルール)などのご相談は、お問い合わせからどうぞ。
まとめ
- deny で止まらない経路(全体検索・スクリプト経由・環境変数経由)は、hooks で実行前に人の確認を通す形にします
- hooks は3本。送信前の認証情報チェック、危険なコマンドの確認、PR への「AI利用あり」。リポジトリにコミットすれば全員に効きます
- 止めた事象はログに残し、誤検知を見ながら判定を直します。CLAUDE.md には「止まったら人に返す」振る舞いを書きます
- 判定はパターン一致で万能ではありません。本番の認証情報を手元に置かない運用の上に重ねる保険として使います
- 設定一式:ks-rogers/claude-code-guardrails
よくある質問
Q.Claude Code の hooks とは何ですか?
A.Claude Code が特定の動作をする直前・直後に、自分で用意したスクリプトを実行させる仕組みです。たとえば、ユーザーがプロンプトを送る前(UserPromptSubmit)や、Bash などのツールを実行する前(PreToolUse)に動かせます。スクリプトの結果によって、その動作を止めたり、人に確認を求めたりできます。
Q.deny の設定があれば hooks は不要ではないですか?
A.deny はファイルを直接開く操作(Read ツール、cat、head、tail、リダイレクト)を止めますが、ファイル名を指定しない grep での全体検索、Python などのスクリプト経由の読み出し、source で環境変数に入れて使う経路は止められません。hooks は、こうした経路のコマンドを実行前に検出して、人の確認を求めるために使います。
Q.hooks はどこに置けばチーム全員に効きますか?
A.リポジトリ直下の .claude/settings.json に hooks の設定を書き、スクリプトを .claude/hooks/ に置いてコミットします。クローンした全員に同じ設定がかかります。Claude Code が読むのはセッションを起動したディレクトリの設定なので、複数のリポジトリを親ディレクトリにまとめて開く運用では、親側の設定にまとめて書きます。
Q.この設定で秘密情報の漏えいは防げますか?
A.「うっかり読ませる・貼り付ける」はかなり減らせますが、万能ではありません。判定はパターン一致なので、見たことのない形の秘密情報は通ります。人がファイルを開いてコピーし、チャットに貼る行為も防げません。最も確実なのは、AI が読める場所に本番の認証情報を置かないことで、この設定はその上に重ねる保険です。