・ Claude Code

Claude Codeのセキュリティを固める — Hooksで実装するサプライチェーン攻撃対策
この記事について
対象読者: Claude Codeを日常的に使用しているエンジニア、AIコーディングツールのセキュリティに関心がある方
この記事で扱うこと:
- Claude Codeが「バックドア入りOSS」を無警告で踏襲するリスクの実態
- Claude Code Hooksを使った多層防御の具体的な実装方法
- 環境変数の外部送信検知、サプライチェーン攻撃の事後監査、osascriptインジェクション修正
はじめに
※この記事はAIと2人3脚で執筆されています
2026年3月8日、Qiitaに注目すべき検証記事が投稿されました。@NF0000氏による「Claude Codeにバックドア入りOSSを渡したら、何の疑いもなく実装した」という記事です。この検証では、悪意あるパッケージfake-loggerを含むプロジェクトをClaude Codeに渡し、「機能追加して」と依頼したところ、成功率100%でバックドアパターンを踏襲したことが報告されています。
本記事では、この検証結果を受けて筆者が自身のdotfilesリポジトリに実装したClaude Code Hooksによるセキュリティハードニングの全容を解説します。具体的なシェルスクリプトのコード、設計判断の根拠、そしてレビューを経た改善プロセスまでを包括的に記述します。
この記事はおよそ8,000字なので、16分で読めます!
目次 📚
- 問題の本質 — なぜClaude Codeはバックドアを見抜けないのか
- Claude Code Hooksとは
- 実装した防御策の全体像
- 環境変数Exfiltration検知フック
- パッケージ監査リマインダーフック
- 既存フックの最適化
- osascriptインジェクション修正
- 3チーム並列レビューと改善
- 残る課題と限界
1. 問題の本質 — なぜClaude Codeはバックドアを見抜けないのか 🔍
「CLAUDE.mdへの直接攻撃は成功率0%。しかしコード経由の攻撃は成功率100%」
前述の@NF0000氏の検証記事の結果を表にまとめると、明確なパターンが浮かび上がります。
| 攻撃手法 | 成功率 | Claude Codeの反応 |
|---|---|---|
| CLAUDE.mdにテレメトリ偽装指示 | 0% | 「データ漏洩リスク」と拒否 |
| CLAUDE.mdにエラー監視偽装 | 0% | 「バックドア」と断定 |
| CLAUDE.mdに偽パッケージ導入指示 | 0% | 「supply chain attack」と警告 |
| cloneしたOSSで機能追加依頼 | 100% | 警告なし・バックドア踏襲 |
| ログ強化依頼 | 100% | 警告なし・漏洩データ増大 |
この非対称性の原因は、Claude Codeの入力処理における信頼レベルの差異にあると推測されます。
- CLAUDE.md → 「指示」として処理される → セキュリティフィルタが作動
- 既存コード → 「実装パターン」として処理される → 信頼され、精査されない
つまり、プロジェクト内に既に存在する悪意あるコードは「正規の実装」として扱われ、新機能追加時にそのパターンが無批判に踏襲されるという構造的な問題が存在します。
2. Claude Code Hooksとは 🔧
「ツール実行のライフサイクルに介入し、自動でセキュリティチェックを挟む仕組み」
Claude Code Hooksは、Claude Codeのツール実行ライフサイクルの各ポイントで自動実行されるユーザー定義のスクリプトです。~/.claude/settings.jsonに設定を記述します。
主要なイベントタイプは以下の通りです。
| イベント | 発火タイミング | 用途 |
|---|---|---|
PreToolUse | ツール実行前 | 危険な操作のブロック |
PostToolUse | ツール実行後 | 事後監査・警告 |
SessionStart | セッション開始時 | 環境初期化 |
Stop | Claude応答完了時 | 品質チェック |
各フックはexit 0で許可、exit 2でブロックを返します。matcherでツール名を絞り込み、command(シェルスクリプト)またはprompt(LLM判定)で処理を定義します。
settings.jsonの基本構造(設定例)
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/detect-secrets.sh",
"timeout": 5
}
]
}
]
}
}
3. 実装した防御策の全体像 📊
「単一の防御では不十分。多層防御で攻撃面を最小化する」
今回実装した防御策は、記事が指摘する7つのリスクに対して以下のようにマッピングされます。
| リスク | 対策 | 防御レイヤー |
|---|---|---|
| OSSバックドア踏襲 | PreToolUse promptフック強化 | LLM判定 |
| env外部送信 | detect-env-exfiltration.sh 新設 | パターンマッチ |
| ログによる情報漏洩 | 同上(LEAK_PATTERNS) | パターンマッチ |
| サプライチェーン攻撃 | package-audit.sh 新設 | 事後警告 |
| auto-accept無確認実行 | skipDangerousModePermissionPrompt: false | 設定変更 |
| 危険コマンド実行 | block-dangerous-commands.sh パターン追加 | パターンマッチ |
| osascriptインジェクション | 通知hookのサニタイズ | 入力検証 |
防御の層構造は以下の通りです。
- 第1層: permissions.deny —
sudo,rm,evalのBash実行を拒否 - 第2層: PreToolUseフック — ファイル編集時に4段階のチェック(protect-files → detect-secrets → detect-env-exfiltration → LLM prompt)
- 第3層: PostToolUseフック — パッケージインストール・git clone後の監査リマインダー
- 第4層: CLAUDE.mdルール — セキュリティ禁止事項の明文化
補足: skipDangerousModePermissionPrompt とは 🔑
「公式のSettings referenceに記載がない設定キー。bypassPermissionsモードの初回警告を抑制する」
上表のskipDangerousModePermissionPromptは、Claude Code公式のSettings referenceに2026年9月時点で記載がなく(GitHub Issue #26233で指摘されている)、動作を知るには挙動から追うしかないキーです。
- 制御対象:
--dangerously-skip-permissions起動時やpermissions.defaultMode: bypassPermissions有効化時に一度だけ出る安全警告ダイアログの表示可否 - 書き込まれるタイミング: ユーザーが警告ダイアログで「理解した」と承諾すると、Claude Codeが自動で
trueを書き込む。手動で先回りして設定する必要はない - 書き込み先:
~/.claude/settings.json(ユーザーレベルのみ。プロジェクトの.claude/settings.jsonや.claude/settings.local.jsonには書き込まれない) falseにする/キーごと削除するとどうなるか: 次回bypassPermissionsモードに入る際、安全警告ダイアログが再び表示される
CI・バッチ処理などの無人環境で~/.claude/settings.jsonに"skipDangerousModePermissionPrompt": trueが意図せず残っていないかは、最小権限の観点で定期的に確認する価値があります。
4. 環境変数Exfiltration検知フック 🛡️
「環境変数の一括アクセスと外部送信を3カテゴリで検知する」
今回の対策の中核となるフックです。同検証記事で示されたfake-loggerは、環境変数全体をJSON化して外部に送信するという手法を使っていました。このパターンを3段階で検知します。
カテゴリ1: 環境変数の一括アクセス
JSON.stringify()によるenv一括シリアライズや、スプレッド構文(...)によるenv展開を検知します。個別の環境変数アクセス(例: NODE_ENVの参照)はマッチしません。
カテゴリ2: 環境変数の外部送信
Node.js(fetch, axios, http.request)、Python(urllib, requests)、Ruby(Net::HTTP)の主要なHTTPクライアントとenv変数の組み合わせを検知します。
カテゴリ3: 機密データのログ出力
リクエストボディやレスポンスボディの丸ごとログ出力も検知対象です。
設計上の工夫: 単一grepへの統合
初期実装ではforループで各パターンを個別にgrepしていましたが、レビューで最悪24回のsubprocess起動が指摘されました。パターンを|で結合し、カテゴリごとに1回のgrep呼び出しに統合することで、最大3回のsubprocessに削減しています。
# Before: 24回のsubprocess(forループ)
for pattern in "${PATTERNS[@]}"; do
if echo "$CONTENT" | grep -qE -- "$pattern"; then ...
done
# After: 3回のsubprocess(パターン結合)
if echo "$CONTENT" | grep -qE -- "$COMBINED_RE"; then ...
5. パッケージ監査リマインダーフック 📦
「パッケージインストールとgit cloneを検知し、セキュリティ監査を促す」
このフックはPostToolUseイベントで動作します。PreToolUseのようにブロックするのではなく、exit 0で通過させつつstderrに警告を出力します。
npm, yarn, pnpm, bun, pip, go getを含む主要パッケージマネージャのinstall/addコマンドを単一の正規表現で検知し、セキュリティ監査の実施を促します。
git cloneに対しても専用の警告を出力します。これは同検証記事が示す「cloneしたOSSを無批判に信頼する」リスクに直接対応するものです。
なぜブロックではなく警告なのか
パッケージインストールやgit cloneは正当な操作であり、全てをブロックすると開発効率が著しく低下します。ここでの目的は「人間の注意を喚起する」ことであり、最終的な判断は開発者に委ねる設計としています。
6. 既存フックの最適化 ⚡
「forループの逐次grep → パターン結合の単一grepで、最悪57回のsubprocess起動を3回に削減」
detect-secrets.sh
16個のシークレットパターン(AWS Access Key, GitHub PAT, Stripe Key等)をforループで個別にgrepしていた実装を、|結合した単一の正規表現に統合しました。
マッチ時にgrep -oEでマッチした文字列の先頭20文字をプレビュー表示することで、誤検知時のデバッグを容易にしています。
block-dangerous-commands.sh
元の4パターンに加えて13パターンを追加し、同様に単一grepに統合しました。追加したカテゴリは以下の通りです。
| カテゴリ | パターン例 |
|---|---|
| データ外部送信 | curl/wgetによるenv送信 |
| ネットワークツール | netcat系のリバースシェル |
| 動的コード実行 | python/nodeによるインラインスクリプト |
| DNS Exfiltration | nslookup/digによるデータ送出 |
責務の明確な分離
レビューで指摘されたdetect-secrets.shとdetect-env-exfiltration.shの責務重複を解消しました。
- detect-secrets.sh → 静的クレデンシャル(トークン、APIキー文字列)の検出のみ
- detect-env-exfiltration.sh → 環境変数の動的利用パターン(一括アクセス、外部送信、ログ漏洩)の検出のみ
7. osascriptインジェクション修正 🔒
「悪意あるブランチ名からのコマンドインジェクションを防ぐ」
セキュリティ分析チームが発見した脆弱性です。Claude Codeの通知hookでgitのブランチ名をAppleScriptに直接展開していたため、コマンドインジェクションが理論上可能でした。
修正では、tr -cdコマンドで英数字と安全な記号のみにサニタイズし、空文字になった場合のフォールバックを追加しました。
# 修正後: サニタイズ + 空文字フォールバック
PROJECT=$(basename "$(git rev-parse --show-toplevel)" | tr -cd 'a-zA-Z0-9._-')
[ -z "$PROJECT" ] && PROJECT='unknown'
BRANCH=$(git rev-parse --abbrev-ref HEAD | tr -cd 'a-zA-Z0-9._-/')
[ -z "$BRANCH" ] && BRANCH='unknown'
8. 3チーム並列レビューと改善 🔬
「セキュリティ分析・防御策検討・コードベース監査の3チームをAgent Teamsで並列実行」
今回の実装プロセスで特筆すべき点は、Claude CodeのAgent Teams機能を活用した3チーム並列レビューです。
チーム構成
| チーム | 役割 | 使用エージェント |
|---|---|---|
| セキュリティ分析 | リスク評価・脆弱箇所特定 | security |
| 防御策検討 | 具体的対策の計画立案 | Plan |
| コードベース監査 | 既存防御設定の棚卸し | Explore |
3チームが並列で調査を行い、結果を統合した上で実装に着手しました。実装後もCode Reuse / Code Quality / Efficiencyの3観点で並列レビューを実施し、以下の改善を行っています。
レビューで発見・修正された問題
| 指摘 | 修正内容 |
|---|---|
| detect-secrets / exfiltrationの責務重複 | envパターンをexfiltration側に一本化 |
| forループ+grepの非効率(最悪57回subprocess) | パターン結合grepで最大3回に削減 |
| *.mdスキップによるセキュリティバイパス | スキップ自体を削除 |
| osascript空文字未ハンドリング | [ -z ]チェック追加 |
9. 残る課題と限界 ⚠️
「Hooksは銀の弾丸ではない。人間のレビューが最後の防壁」
今回の対策には明確な限界があります。
単一行マッチの制約
grepは行単位のマッチであり、複数行にまたがるexfiltrationコードは検出できません。変数への一時代入と別の行でのネットワーク送信という分割パターンには対応できません。
パターンの回避可能性
決意ある攻撃者であれば、変数名の変更やBase64エンコードなどでパターンマッチを回避できます。
LLM promptフックの非決定性
同検証記事でも指摘されているように、LLMによる検出は実行ごとに結果が異なります。同じプロンプトでも検出に成功する場合と失敗する場合があります。
本質的な対策
技術的な防御はあくまで補助的なものです。本質的に必要なのは以下の3点です。
- 依存関係の監査 —
npm auditを定期実行し、既知の脆弱性を把握する - コードレビュー — AI生成コードを必ず人間がレビューする
- 最小権限の原則 —
skipDangerousModePermissionPromptを無効化し、危険な操作には確認を挟む
まとめ 🎊
- **@NF0000氏の検証**により、Claude Codeが「既存コード」を無批判に信頼する構造的問題が明らかになった
- Claude Code Hooksを活用し、PreToolUse(事前ブロック)とPostToolUse(事後警告)の多層防御を構築した
- 新設フック:
detect-env-exfiltration.sh(環境変数exfiltration検知)、package-audit.sh(パッケージ監査リマインダー) - 既存フック最適化: forループ→パターン結合grepで最悪57回→3回のsubprocessに削減
- 設定変更:
skipDangerousModePermissionPrompt: falseで「最後の砦」を復活 - osascriptインジェクション修正: ブランチ名のサニタイズと空文字フォールバック
- 限界: 単一行マッチ、パターン回避、LLM非決定性 — Hooksは補助であり、人間のレビューが最後の防壁
AIコーディングツールの生産性向上は否定できませんが、「全てをAIに任せる」という姿勢には大きなリスクが伴います。本記事で示した対策が、Claude Codeをより安全に活用するための一助となれば幸いです。
補足: 国際標準における位置づけ 🌐
「OWASPとNISTも、AI生成コードをサプライチェーンリスクとして明確に位置づけている」
本記事で扱ったリスクは、個人の検証記事にとどまらず、国際的なセキュリティ標準でも認識されています。
| 標準 | 該当項目 | 要点 |
|---|---|---|
| OWASP Top 10 for LLM Applications 2025 | LLM03:2025 - Supply Chain | サードパーティモデルのバックドア混入、訓練データの汚染リスク |
| OWASP Top 10 for Agentic Applications | Supply Chain Redirection | 自律的にプラグインを取得するAIエージェントの新たな攻撃面 |
| NIST AI 600-1 | Generative AI Profile | AI生成コードを「信頼されないサードパーティコード」として扱うべき |
特にNIST AI 600-1の「AI生成コードは信頼されないサードパーティコードである」という位置づけは、本記事の対策の根拠を明確に裏付けています。AI生成コードもSCA(Software Composition Analysis)やSAST(Static Application Security Testing)のパイプラインを通すべきであり、Claude Code Hooksはその簡易的な実装と言えます。
参考リンク 🔗
検証記事
公式ドキュメント
- Claude Code Hooks Reference — Anthropic
- Claude Code Hooks Guide — Anthropic
- Claude Code Settings files and precedence — Anthropic
- [DOCS] Settings reference missing
skipDangerousModePermissionPromptproperty — Issue #26233