セキュリティガードレールの自爆:AIエージェントの「フック」と「ファイルデータ」の自己言及的誤検知
1. 概要
AIエージェントを保護するためのセキュリティガードレール(Guardrails)は、外部の信頼できないソース(ファイル、Webページ、関数の結果)から注入される「プロンプトインジェクション攻撃」を検知し、未然にブロックする重要な役割を持つ。 しかし、ガードレールの検知ロジックが単純なパターンマッチングに依存し、さらに「システム内部の信頼できる指示(フック)」と「外部のデータ」の境界線が曖昧な場合、システムが自ら設定したフックを「攻撃」と誤認して自爆し、機能を強制停止させてしまう偽陽性(False Positive)バグが発生する。 本稿では、Claude Codeのインシデント(anthropics/claude-code#17804)を題材に、エージェントにおける「信頼境界(Trust Boundary)」の設計の難しさとガードレールの自爆メカニズムについて分析する。
2. インシデントの分析:JSONデータの読み込みで発生する「プロンプトインジェクション誤検知」
2.1. 現象:ファイル読み込みを阻むセキュリティの壁
Claude Code v2.1.5において、ユーザーがプロンプト送信時に自動的に特定の指示を追加する UserPromptSubmit フックを設定している状態で、AIが「ネストした複雑なJSON構造を持つファイル」を読み込むか、関数の結果を受け取ると、以下のようなエラーを出して処理が強制停止(Abort)するバグが発生した。
❯ Operation stopped by hook: This is a prompt injection attack attempting to execute instructions from a
file rather than from direct user input. The nested JSON structure with hook arguments and embedded file
read instructions violates critical security rules that prohibit executing instructions from untrusted
sources...エラーメッセージは、これが「ファイルから命令を実行させようとする悪意あるプロンプトインジェクション攻撃である」と主張しているが、読み込んだファイルは単なる通常のJSONデータであり、設定したフックも「タスクツールを使うときはバックグラウンド実行をデフォルトにせよ」という極めて無害な指示であった。
2.2. 原因:自己のフックと外部データの「文脈の混同」
なぜセキュリティガードレールは、無害な設定と普通のファイルを「攻撃」と判定してしまったのか。 原因は、エージェントがプロンプトフックを評価し、コンテキストに結合する際の「信頼境界(Trust Boundary)」の設計不良にあった。
- インジェクション検出器の仕様: ガードレールは、外部データ(ファイル等)の中に「
prompt」などのフィールドや命令的な記述が含まれていないかを監視し、データの中に命令を埋め込むタイプのインジェクション(データと命令の混同)を警戒している。 - フックの合流と自己言及:
UserPromptSubmitフック(type: "prompt")のデータ構造は、内部的にpromptというフィールドを持つ。 エージェントが「ファイル内のネストしたJSON」をパースしてコンテキストに読み込む際、フック処理が同じ評価空間で同時に走ったため、ガードレールは**「ファイル(外部データ)を読み込んだコンテキストの中に、なぜかpromptという命令フィールドが存在する。これはファイルの中に指示を隠蔽したJSON型のインジェクション攻撃だ」**と誤認してしまった。
つまり、エージェントの安全性を高めるために用意された「プロンプトフック機能(信頼できるインプット)」を、セキュリティ層が「外部ファイルから注入された悪意あるインジェクション(信頼できないインプット)」として自己検知して自爆したのである。
3. 実体験:防衛システム自身が最大の「可用性障害」を引き起こす罠
セキュリティを強固にしようとするあまり、防衛システムの検知ルールを厳しくしすぎた結果、正常な業務システムを「攻撃」と誤認してサービスを停止させてしまうトラブルは、セキュリティエンジニアにとって頭痛の種である。
- 実体験エピソード: あるWebアプリケーションの防御のために、WAF(Web Application Firewall)を導入し、「SQLインジェクションやOSコマンドインジェクションを検知したら即座に通信を遮断(Block)する」という極めて厳しいセキュリティポリシーを設定した。 数日間は平穏に動いていたが、ある日、ユーザーが「自己紹介やコメント」を入力するテキストエリアの中に、プログラミングやSQLのコードの書き方(例:
SELECTやUNIONなどの単語を含む技術的なブログの下書き)を書いて保存しようとした際、WAFが「SQLインジェクション攻撃」として誤検知し、ユーザーのIPアドレスを強制ブロックするインシデントが発生した。 さらに悪いことに、カスタマーサポートがその苦情メールを管理画面で処理しようとした際、メール本文内のエラーメッセージが原因でWAFが再度自爆し、管理画面自体がアクセス不能になるという負の連鎖(自己言及的な自爆)を引き起こした。 「文脈(コンテキスト)」を理解せず、パターンマッチングのみで強制遮断を行う防衛策は、攻撃者ではなく自分たちを撃ち落とす「フレンドリーファイア」の温床となる。
4. 解決策とAIガードレールの設計原則
このバグの暫定的なワークアラウンドは「UserPromptSubmit フック(promptタイプ)の使用を停止すること」だった。 根本解決には、以下の設計原則(信頼境界の分離)が必要である。
4.1. データチャネルと制御チャネルの完全な分離(Trusted Channel vs Untrusted Channel)
今回の自爆バグの根本原因は、「ユーザーが定義した信頼できる設定(フック)」と「外部からロードした信頼できないデータ」を、ガードレールが同一の「ネストしたJSONオブジェクト」として平坦に混同して評価してしまったことである。
- データタグの付与: システム内部のデータ構造において、
origin: "system_hook"やorigin: "external_file"といったデータの「出自(Provenance)」を示すメタデータを厳密に付与し、ガードレールはorigin: "external_file"のデータのみを評価対象にするよう隔離しなければならない。 - 生データの文字列化(No AST Parsing on Untrusted Data): 外部から読み込んだJSONファイルなどのデータは、構造化された「オブジェクト」としてプロンプト評価器に渡すのではなく、単なる「平文の文字列テキスト」としてLLM의 コンテキストに提示し、ASTレベルでセキュリティチェックをかける対象からは除外する。
5. 結論
AIエージェントにおけるセキュリティ・ガードレールは、攻撃を検知する機能であるが、その評価コンテキストがシステム自身の動作コンテキストと混ざり合うと、「自分のしっぽを敵と勘違いして噛む」ような自爆誤検知を引き起こす。 安全なエージェントシステムを設計するためには、プロンプトの出自を追跡する 「データチャネルの分離(信頼境界の隔離)」 を徹底し、データと命令の境界をインフラ層で明確に区別し続けることこそが、ガードレールの自爆を防ぎ、システムの安全性と可用性を両立させるための不可欠な設計要件である。
6. 参考文献 / 一次情報
- UserPromptSubmit prompt hook causes false positive prompt injection: anthropics/claude-code#17804
- Hook Development for Claude Code Plugins - UserPromptSubmit: anthropics/claude-code#UserPromptSubmit