Claude Codeを始めたばかりの方へ: OWASPやMCPという用語が出てきますが、「AIツールを安全に使うためのセキュリティ対策集」だと思って読んでください。各hookのコードはコピペで動きます。
OWASPが「MCP Top 10」を公開した。
:::details 初心者向け: OWASPとは
OWASP(Open Worldwide Application Security Project)は、ソフトウェアのセキュリティを改善するための国際的な非営利団体です。「ウェブアプリの危険トップ10」のような、開発者が知っておくべきセキュリティリスクのランキングを定期的に公開しています。いわばセキュリティの「健康診断チェックリスト」を作っている組織です。
:::
MCPサーバーとAIエージェントに特有の10のセキュリティリスクをまとめたものだ。
:::details 初心者向け: MCPとは
MCP(Model Context Protocol)は、AIモデルが外部のツールやサービスと連携するための通信規格です。たとえばClaude CodeがGitHubやデータベースと連携するとき、MCPを使って情報をやり取りします。便利な反面、接続先が増えるほどセキュリティリスクも増えます。
:::
「で、具体的に何をすればいいの?」
Claude Codeを使っているなら、答えはhookだ。hookはClaude Codeの全ツール呼び出しに割り込んで(ツールが実行される「直前」にチェックを挟んで)、危険な操作をブロックできる。OWASP MCP Top 10の10リスク中、9つはhookで直接防御できる。
この記事では、各リスクに対応するhookの実装を示す。コピペで動く。
前提
- Claude Code がインストール済み
-
~/.claude/settings.jsonにhookを登録する方法を知っている(公式ドキュメント)
hookの基本を知らない場合は、第2章を無料公開中のZenn Bookで解説している。
MCP01: Token Mismanagement & Secret Exposure
リスク: ハードコードされた認証情報、長寿命トークン、シークレットがモデルのメモリやプロトコルログに露出する。
防御hook: credential-exfil-guard
エージェントが認証情報を探す操作(env | grep TOKEN、cat ~/.ssh/id_rsa、find / -name "*.token"など)をブロックする。
#!/bin/bash
# credential-exfil-guard.sh — PreToolUse hook on "Bash"
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
[ -z "$COMMAND" ] && exit 0
# Pattern: env/printenv piped to grep for secrets
if echo "$COMMAND" | grep -qiE '(env|printenv|set)\s*\|.*grep.*(token|secret|key|password|credential|auth)'; then
echo "BLOCKED: MCP01 — credential enumeration detected" >&2
exit 2
fi
# Pattern: reading known credential files
if echo "$COMMAND" | grep -qiE 'cat.*(\.ssh/|\.aws/|\.env|credentials|\.token|/etc/shadow)'; then
echo "BLOCKED: MCP01 — credential file access detected" >&2
exit 2
fi
exit 0
関連hookの一覧(cc-safe-setupに含まれるもの):
-
hardcoded-secret-detector.sh— コード内のハードコードされたシークレットを検出 -
write-secret-guard.sh— シークレットをファイルに書き込むのを防止 -
no-secrets-in-logs.sh— ログにシークレットが含まれないよう監視 -
output-secret-mask.sh— 出力内のシークレットをマスク -
no-default-credentials.sh— デフォルト認証情報の使用を検出
MCP02: Privilege Escalation via Scope Creep
リスク: 緩く定義された権限が時間とともに拡大し、リポジトリ変更やデータ流出などの意図しない操作を許す。
防御hook: no-sudo-guard + permission-audit-log
#!/bin/bash
# no-sudo-guard.sh — PreToolUse hook on "Bash"
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
[ -z "$COMMAND" ] && exit 0
if echo "$COMMAND" | grep -qE '^\s*sudo\s|;\s*sudo\s|\|\s*sudo\s'; then
echo "BLOCKED: MCP02 — sudo execution (privilege escalation risk)" >&2
exit 2
fi
if echo "$COMMAND" | grep -qE 'chmod\s+[0-7]*7|chmod\s+\+s|chown\s+root'; then
echo "BLOCKED: MCP02 — dangerous permission change" >&2
exit 2
fi
exit 0
関連hook:
-
allow-protected-dirs.sh— 保護ディレクトリへの書き込みを制御 -
no-root-write.sh— rootユーザーとしての書き込みを防止 -
permission-audit-log.sh— 権限変更を記録
MCP03: Tool Poisoning
リスク: 攻撃者がツールやプラグインの出力を改ざんし、モデルの挙動を操作する。
防御hook: hook-tamper-guard
Claude Code自身がhookを書き換えて、セキュリティ対策を弱める攻撃を防ぐ。「誰が見張り番を見張るのか」問題の解決策。
#!/bin/bash
# hook-tamper-guard.sh — PreToolUse hook on "Edit|Write|Bash"
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
case "$TOOL" in
Edit|Write)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
if echo "$FILE" | grep -qE '\.claude/hooks/|\.claude/settings\.json'; then
echo "BLOCKED: MCP03 — hook file modification (tamper prevention)" >&2
exit 2
fi
;;
Bash)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
if echo "$CMD" | grep -qE '(mv|cp|rm|sed|awk|echo|cat|tee).*\.claude/(hooks|settings)'; then
echo "BLOCKED: MCP03 — hook directory manipulation" >&2
exit 2
fi
;;
esac
exit 0
関連hook:
-
checkpoint-tamper-guard.sh— チェックポイントの改ざんを防止 -
edit-verify.sh— 編集後のファイル整合性を検証 -
test-exit-code-verify.sh— テスト結果の偽報告を防止
MCP04: Software Supply Chain Attacks & Dependency Tampering
リスク: 侵害された依存関係がエージェントの挙動を変えたり、バックドアを導入する。
:::details 初心者向け: サプライチェーン攻撃とは
サプライチェーン攻撃とは、ソフトウェアが使っている「部品」(ライブラリやパッケージ)を通じて行われる攻撃です。食品に例えると、レストランの料理自体は安全でも、仕入れた食材が汚染されていたら食中毒になる——ソフトウェアも同じで、信頼して使っているライブラリに悪意あるコードが混入すると、自分のアプリ全体が危険にさらされます。
:::
「AIに任せて大丈夫なのか」という不安を持ったまま800時間使い続けた記録は非エンジニアがClaude Codeを800時間走らせた——失敗と学びの全記録(¥800・第2章まで無料)に書いた。
防御hook: dependency-install-guard
#!/bin/bash
# dependency-install-guard.sh — PreToolUse hook on "Bash"
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
[ -z "$COMMAND" ] && exit 0
# Allow lockfile installs
echo "$COMMAND" | grep -qE '^npm\s+(ci|install)\s*$' && exit 0
echo "$COMMAND" | grep -qE 'pip install -r' && exit 0
# Block unknown package installations
if echo "$COMMAND" | grep -qE 'npm install\s+\S|pip install\s+\S|gem install\s+\S|cargo add\s+\S|go get\s+\S'; then
PACKAGE=$(echo "$COMMAND" | grep -oE '(npm install|pip install|gem install|cargo add|go get)\s+\S+' | awk '{print $NF}')
echo "BLOCKED: MCP04 — unreviewed package: $PACKAGE" >&2
exit 2
fi
exit 0
関連hook:
-
dependency-audit.sh— 依存関係の脆弱性をチェック -
dependency-version-pin.sh— バージョン固定を強制 -
check-dependency-age.sh— 古すぎる依存関係を警告 -
check-dependency-license.sh— ライセンス互換性を確認 -
no-force-install.sh—--forceフラグを禁止 -
npm-script-injection.sh— npmスクリプト経由の攻撃を検出
MCP05: Command Injection & Execution
リスク: AIエージェントが未検証の入力からシステムコマンドを実行する。
防御hook: banned-command-guard
#!/bin/bash
# banned-command-guard.sh — PreToolUse hook on "Bash"
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
[ -z "$COMMAND" ] && exit 0
# Block destructive commands
if echo "$COMMAND" | grep -qE 'rm\s+-rf\s+/|rm\s+-rf\s+~|mkfs\.|dd\s+if=|>\s*/dev/sd|chmod\s+777\s+/'; then
echo "BLOCKED: MCP05 — destructive system command" >&2
exit 2
fi
# Block eval with external input
if echo "$COMMAND" | grep -qE 'eval\s+\$|eval\s+"?\$|bash\s+-c\s+"?\$'; then
echo "BLOCKED: MCP05 — eval with variable input (injection risk)" >&2
exit 2
fi
exit 0
関連hook:
-
rm-safety-net.sh— rmコマンドの安全ネット -
no-eval.sh— eval使用を禁止 -
no-exec-user-input.sh— ユーザー入力の直接実行を防止 -
sql-injection-detect.sh— SQL injection検出 -
terraform-guard.sh— Terraformの危険操作を防止 -
prompt-injection-guard.sh— プロンプトインジェクション防御
MCP06: Intent Flow Subversion
リスク: コンテキストに埋め込まれた悪意ある命令がエージェントの目的を乗っ取る。
防御hook: prompt-injection-detector
#!/bin/bash
# prompt-injection-detector.sh — UserPromptSubmit hook
INPUT=$(cat)
PROMPT=$(echo "$INPUT" | jq -r '.prompt // empty' 2>/dev/null)
[ -z "$PROMPT" ] && exit 0
if echo "$PROMPT" | grep -qiE 'ignore (all |previous |prior )?instructions|disregard (your|the) rules|you are now|new persona|system prompt|forget everything'; then
echo "⚠ MCP06: Possible prompt injection detected" >&2
echo " Review the prompt carefully before proceeding." >&2
fi
exit 0
関連hook:
-
env-drift-guard.sh— 環境設定の意図しない変更を検出 -
reinject-claudemd.sh— CLAUDE.mdの再注入で指示を保護
MCP07: Insufficient Authentication & Authorization
リスク: MCPサーバーが適切な認証・認可なしでリクエストを処理する。
hookで直接対処するのは難しいが、認証関連の操作を監視することはできる。
防御hook: session-start-safety-check
#!/bin/bash
# session-start-safety-check.sh — Notification hook on "SessionStart"
# セッション開始時に未コミット変更や認証状態を確認
echo "=== Session Safety Check ===" >&2
# Check git status
if git status --porcelain 2>/dev/null | grep -q '^'; then
echo "⚠ Uncommitted changes detected. Consider committing before starting." >&2
fi
# Check auth status
if ! gh auth status &>/dev/null; then
echo "⚠ GitHub CLI not authenticated." >&2
fi
exit 0
関連hook:
-
git-author-guard.sh— コミットの著者を検証
MCP08: Lack of Audit and Telemetry
リスク: テレメトリの不足がインシデント調査を妨げる。
:::details 初心者向け: テレメトリとは
テレメトリとは、システムの動作状況を自動的に記録・収集する仕組みです。車のドライブレコーダーのようなもので、「いつ、何が起きたか」を後から確認できます。事故が起きたとき、ドライブレコーダーがなければ原因を特定できない——テレメトリがないシステムも同じです。
:::
防御hook: permission-audit-log
#!/bin/bash
# permission-audit-log.sh — PostToolUse hook
# 全ツール呼び出しをログに記録する
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
TIMESTAMP=$(date -u '+%Y-%m-%dT%H:%M:%SZ')
LOG_DIR="${HOME}/.claude/audit"
mkdir -p "$LOG_DIR"
echo "${TIMESTAMP} ${TOOL}" >> "${LOG_DIR}/tool-calls.log"
exit 0
関連hook:
-
session-summary-stop.sh— セッション終了時にサマリーを生成 -
session-state-saver.sh— セッション状態を保存 -
check-error-logging.sh— エラーログの漏れを検出
MCP09: Shadow MCP Servers
リスク: 組織の管理外で動作するMCPサーバーがセキュリティガバナンスを迂回する。
防御hook: mcp-server-guard
エージェントが勝手にMCPサーバーを追加・起動するのをブロックする。承認済みサーバーのallowlist方式。
:::details 初心者向け: allowlistとは
allowlist(許可リスト)とは、「これだけは許可する」というリストのことです。学校の出入りに例えると、「在校生名簿に載っている人だけ入れる」方式です。リストにないものは全てブロックされるので、未知の危険を防ぐのに有効です。逆の「blocklist(拒否リスト)」は「この人だけ入れない」方式で、リストに載っていない新しい危険には対応できません。
:::
#!/bin/bash
# mcp-server-guard.sh — PreToolUse hook on "Edit|Write|Bash"
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
case "$TOOL" in
Edit|Write)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
# Block MCP config file modification
if echo "$FILE" | grep -qE '\.mcp\.json$|mcp-config\.json$'; then
echo "BLOCKED: MCP server configuration change detected." >&2
exit 2
fi
# Block adding mcpServers to settings
if echo "$FILE" | grep -qE 'settings\.json$'; then
CONTENT=$(echo "$INPUT" | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
if echo "$CONTENT" | grep -qiE 'mcpServers'; then
echo "BLOCKED: MCP server addition to settings." >&2
exit 2
fi
fi
;;
Bash)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
[ -z "$CMD" ] && exit 0
if echo "$CMD" | grep -qE 'npx.*@.*mcp|node.*mcp-server|python.*mcp.*server'; then
# Allowlist: customize for your approved servers
echo "$CMD" | grep -qE '@playwright/mcp|godot-mcp' && exit 0
echo "BLOCKED: Unknown MCP server launch." >&2
exit 2
fi
;;
esac
exit 0
MCP10: Context Injection & Over-Sharing
リスク: 共有コンテキストを通じて、あるタスクの機密情報が別のタスクやエージェントに漏洩する。
防御hook: sensitive-regex-guard + context-snapshot
#!/bin/bash
# sensitive-regex-guard.sh — PostToolUse hook
# ツール出力に機密パターンが含まれていないかチェック
INPUT=$(cat)
OUTPUT=$(echo "$INPUT" | jq -r '.tool_output // empty' 2>/dev/null)
[ -z "$OUTPUT" ] && exit 0
# Check for sensitive patterns in output
if echo "$OUTPUT" | grep -qiE '[0-9]{4}[- ]?[0-9]{4}[- ]?[0-9]{4}[- ]?[0-9]{4}|[A-Za-z0-9+/]{40,}={0,2}|-----BEGIN (RSA |EC )?PRIVATE KEY'; then
echo "⚠ MCP10: Potential sensitive data detected in tool output" >&2
echo " Review output before sharing across contexts." >&2
fi
exit 0
関連hook:
-
context-snapshot.sh— コンテキストのスナップショットを保存 -
memory-write-guard.sh— メモリへの書き込みを制御 -
error-memory-guard.sh— エラー情報のメモリ残留を防止 -
no-sensitive-log.sh— 機密情報のログ出力を防止 -
session-handoff.sh— セッション引き継ぎ時の情報管理
まとめ: OWASP MCP Top 10 × hook対応表
| リスク | hookで防御可能か | 対応hook数 |
|---|---|---|
| MCP01 Token/Secret | ✅ | 20+ |
| MCP02 Privilege Escalation | ✅ | 6 |
| MCP03 Tool Poisoning | ✅ | 9 |
| MCP04 Supply Chain | ✅ | 18 |
| MCP05 Command Injection | ✅ | 19 |
| MCP06 Intent Subversion | ✅ | 3 |
| MCP07 Auth | △(監視のみ) | 2 |
| MCP08 Audit | ✅ | 10 |
| MCP09 Shadow MCP | ✅ | 1 |
| MCP10 Context | ✅ | 19 |
10リスク中9つをhookで対策でき、合計100以上のhook実装例がある。
📌 関連記事: Claude Codeのhookが動かない——5分で原因を特定する診断ガイド
あなたのClaude Code、OWASP MCP Top 10に対応していますか?
自分のトークン消費パターンを確認したい方へ
Token Checkupで5つの質問に答えるだけでトー���ン消費��診断ができる。Hook Selectorで最適なhookセットも分かる。
📖 トークン消費に困っているなら → Claude Codeのトークン消費を半分にする——800時間の運用データから見つけた実践テクニック(¥2,500・はじめに+第1章 無料)
⚠️ Opus 4.7ユーザーへ(2026年4月17日追記)
4月16日のOpus 4.7デフォルト化で、トークン消費が最大4倍に急増しています(#49541)。安全分類器のバグで20件以上のデータ損失も報告されています(#49618)。
- 緊急対策:
npx cc-safe-setup --opus47 - 詳細: Opus 4.7 Survival Guide / Safety Scanner
⚠️ CVE-2026-21852(2026年4月公開): プロジェクト内.claude/settings.json経由でAPIキー窃盗。対策: npx cc-safe-setup(ユーザーレベル設定で免疫)→ 詳細
📚 主張と実態の乖離の事例の整理と防衛の手順
本記事の OWASP MCP Top 10 の hook での予防の延長で、 hook が防衛できない領域 (純粋な文の生成の系統、 認識はあるが止まらない構造) の事例の集積が継続的に発生しています。 hook の限界と補完の経路の整理。
5/22 発売の Claude Code Claim-Verify Handbook で、 同型の主張と実態の乖離の事例を 130 件 (本文 15 件 + 付録 D 115 件) に整理した試し読み (無料、 約 9,900 字、 JP) を公開済。 4 月から 5 月の運用の事故の総括は、 Postmortems (Gumroad、 ¥4,350) に納めています (試し読み Gist - Incident #1: Cache TTL silent regression)。
購入の検討の判断の助け (Should I buy the Claim-Verify Handbook?) の対話型の道具で、 無料の hook の解説で十分の場合の判定の経路も articulate しています。