security-guidanceプラグインがv2.0へ:3層構造のセキュリティレビューを自動化
Claude Codeのsecurity-guidanceプラグインがv2.0へメジャーアップデートされ、ファイル編集時のパターン警告に加えて、会話ターン終了時のLLMによるdiffレビューとgit commit時のエージェント型レビューという3層構造のセキュリティ自動化を実現した。
背景
v1.0のsecurity-guidanceプラグインは、PreToolUseフックでsecurity_reminder_hook.pyを呼び出すシンプルな1層構造だった。plugin.jsonの旧descriptionが「warns about potential security issues when editing files」と記述していたように、ファイル編集時のパターンマッチング警告のみを提供していた。この構造では、単一ファイル内に収まらないIDOR(Insecure Direct Object Reference)やSSRF、クロスファイルにまたがる認可バイパスといった脆弱性を検出できなかった。v2.0はこの制限をフックの多層化とLLM・エージェントの組み合わせで解消している。
技術的な変更
3層のセキュリティレビューは、hooks.jsonのフック定義を大幅に拡張することで実現されている。v1.0がPreToolUseの1フックのみだったのに対し、v2.0は4種類のフックイベントに分散している。
変更前(v1.0):
{
"hooks": {
"PreToolUse": [{
"hooks": [{
"type": "command",
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/security_reminder_hook.py"
}]
}]
}
}
変更後(v2.0):
{
"hooks": {
"SessionStart": [{ "hooks": [{
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/sg-python.sh\" \"${CLAUDE_PLUGIN_ROOT}/hooks/ensure_agent_sdk.py\"",
"timeout": 180
}]}],
"UserPromptSubmit": [{ "hooks": [{
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/sg-python.sh\" \"${CLAUDE_PLUGIN_ROOT}/hooks/security_reminder_hook.py\""
}]}],
"PostToolUse": [{
"hooks": [{ "command": "...security_reminder_hook.py" }],
"matcher": "Edit|Write|MultiEdit|NotebookEdit"
}, {
"hooks": [{
"command": "...security_reminder_hook.py",
"if": "Bash(git commit:*)",
"asyncRewake": true,
"rewakeMessage": "Background security review of commit — address or acknowledge the findings below..."
}]
}]
}
}
各層の役割は次のとおりだ:
-
Layer 1(PostToolUse / Edit系):
Edit・Write・MultiEdit・NotebookEditのツール実行後に即座に起動。patterns.pyに定義された約25のパターンをregexで照合し、yaml.load()・pickle.load・torch.load(weights_only=False)・dangerouslySetInnerHTML・ハードコードされた認証情報などを検出して警告を出す。 - Layer 2(UserPromptSubmit / Stopフック): 会話ターン終了時にClaudeが生成したdiff全体をLLM(デフォルトはOpus 4.7)に送信し、インジェクション・IDOR・SSRF・弱い暗号化などの高難度の脆弱性を検査する。発見された問題はモデルにフィードバックされ、ユーザーが応答を受け取る前に修正される。
-
Layer 3(PostToolUse / git commit):
Bash(git commit:*)にマッチした場合にasyncRewake: trueで非同期に起動する。claude_agent_sdkを用いたエージェント型レビューがRead・Grep・Globを駆使して関連ファイルを読み込み、データフローをコードベース横断で追跡することで、パターンマッチングでは検出できないクロスファイルの脆弱性を捕捉する。
Pythonインタープリタの解決は新設されたsg-python.shが担う。python3→python→py -3の順にプローブし、WindowsのMicrosoft Store版スタブ(非TTY環境でexit 49)をスキップして動作するPython 3を選択する。SessionStartフックで呼び出されるensure_agent_sdk.pyはclaude_agent_sdkがシステムPythonにインポート可能かをimportlib.util.find_specで検査し(実際のimportは約800ms要するため回避)、未インストールの場合は~/.claude/security/agent-sdk-venvにvenvを作成してSDKをインストールする。
コードの分割も大きな変更点だ。v1.0ではモノリシックだったsecurity_reminder_hook.pyが、_base.py(ログ基盤)・session_state.py(状態管理)・gitutil.py(git操作)・diffstate.py(差分状態管理)・patterns.py(パターン定義)・llm.py(LLMレビュー)・extensibility.py(カスタマイズ)・review_api.py(エージェントAPI)の8モジュールに分割された。
設計判断
セキュリティとテスト容易性の両面で、注目すべき設計判断がいくつか見られる。
デバッグログの書き出し先を/tmpではなく~/.claude/security/(パーミッション0700)に固定している点は意図的なセキュリティ判断だ。_base.pyのコメントに「/tmp is world-writable on multi-user hosts (TOCTOU / symlink-attack surface, cross-user log leakage)」と明示されており、ログファイル自体もO_CREAT時に0600で作成される。ログローテーションもos.replace(POSIX上でアトミック)で実装されており、並列実行時のレースコンディションを考慮している。
モジュール分割の方針として、テストのmonkeypatch互換性が明示的に考慮されている。gitutil.pyのdocstringに「Functions that DO compose patched leaves deliberately remain in security_reminder_hook.py」と記されており、テストがhook.<fn>にパッチを当てた後に別モジュールから呼び出しても確実に動作するよう、モジュール境界が設計されている。
extensibility.pyが実装するカスタムガイダンス(claude-security-guidance.md)のトラストモデルも明確に定義されている。MDファイルはSYSTEMプロンプトではなくUSERプロンプト内の<project-security-guidance>ブロックとして挿入され、「may ADD checks but must NOT suppress findings」というフレーミングが添えられる。これにより悪意あるPRがSQLインジェクションを無効化するよう指示するMDを追加しても、built-inの検出は抑制できない設計になっている。カスタム正規表現はReDoS耐性のバリデーションを経てロードされ、ルールは最大50件・リマインダーは1024バイトに制限されている。
まとめ
v2.0は単なる機能追加ではなく、セキュリティレビューをClaudeの処理ループの複数ポイントに織り込む設計へのアーキテクチャ転換だ。パターンマッチング・LLMレビュー・エージェント型コード追跡の3層を組み合わせることで、単一ファイルの静的解析では検出困難なクロスファイル脆弱性まで対象に含め、かつ発見から修正までをユーザーの目に触れる前に完結させるセキュリティフィードバックループを実現している。