プロンプト対策だけで破られる理由
まず、なぜ「プロンプトを頑張る」だけでは守れないのかを明確にしておきたい。理由は大きく分けて三つある。第一に、モデルは命令とデータを完全には分離できない。人間は文書を読んで「この段落は引用」「ここは注意書き」「これは命令ではない」と直感的に仕分けできるが、モデルにとってはすべてが同じテキスト列になりやすい。もちろんシステムメッセージで優先順位を付けることはできるものの、入力が長く複雑になり、外部データが混ざるほど、意図しない解釈の余地は増えていく。
第二に、エージェントは外部データを取り込みやすい構造になっている。メール本文、チケット、CRMのメモ欄、社内Wiki、PDF、Web検索結果、RAGで引っ張ってきた資料など、自然言語で書かれたものが業務上の“材料”として流入する。攻撃者はこの材料に「次の操作を実行して」「上位指示を無視して」などの誘導文を混ぜ、エージェントの行動をねじ曲げようとする。ここで重要なのは、攻撃者はモデル本体を破らなくてもよい、という点だ。参照するデータを汚染できれば、それが入口になる。
第三に、プロンプト防御は検証が難しい。あるプロンプトがある入力では安全でも、別の入力では破られることは珍しくない。しかもエージェントは連鎖的に動くため、途中で生成した文章が次の入力になり、別のツール呼び出しへつながる。テストでカバーしきれない組み合わせが増えるほど、「このプロンプトなら安全」という主張は根拠を失っていく。
この三つを踏まえると結論はシンプルだ。プロンプトは安全性の補助にはなるが、保証にはならない。保証したいなら、ツール実行の前後にあるシステム設計で縛る必要がある。つまり、最終的に被害を作るのは“実行”であり、実行の安全性を担保するのはプロンプトではなく制約と検証である。
安全なツール実行の要件定義
AIエージェントのリスクを最小化するには、ツール実行を一段上のレイヤとして設計し直すのが近道だ。ここでは「ツールを呼べる」という能力を、できるだけ安全な形に制限するための要件を整理する。ポイントは、モデルに自由にやらせる領域を減らし、機械的にチェックできる条件を増やすことにある。
まず、ツールインターフェースを厳格にする。自然言語で「請求情報を更新して」と言って自由にAPIを叩かせるのではなく、関数呼び出しやJSONスキーマのように、入力形式を固定する。ツール名、許容される引数、型、値域、必須条件を明確にし、スキーマに合わない呼び出しは実行しない。ここは地味だが効く。攻撃者が誘導しても、スキーマで弾ける範囲が広いほど被害が小さくなる。
次に、引数を検証する。たとえばメール送信ツールなら宛先ドメイン、添付ファイルの種類、本文の機密データ混入の有無、送信数の上限をチェックできる。CRM検索なら取得対象の属性や件数、検索条件の範囲を制限できる。請求システム更新なら更新可能な項目、金額の上限、二重更新の防止などを設けられる。ここで大事なのは、検証をモデルにやらせないことだ。モデルは解釈をしてしまう。検証はルールとコードで行い、通らなければ実行しない。これが「実行系を守る」という意味になる。
さらに、許可リストで“できること”自体を減らす。エージェントのツールセットは最小から始め、必要になったら段階的に増やす。現場では、便利さを理由にツールが増えがちだが、ツールが増えるほど攻撃面が増える。加えて、単一のエージェントに何でも持たせない。顧客対応のエージェントにインフラ変更権限を持たせる理由は本来ないし、障害対応のエージェントに顧客個人情報への広範なアクセスを与える必要もない。権限設計は役割に沿って分割する。これは後段の「分離」にもつながる。
実行前の意図確認も強力だ。エージェントがツールを呼ぶ直前に、「何の目的で」「何を」「どこに対して」実行するのかを構造化して提出させる。提出された意図を、ポリシーエンジンやルールベースで判定する。ここでやりたいのは、自然言語をそのまま信用することではなく、危険な操作に共通する特徴を検出することだ。外部送信、権限変更、破壊的操作、広範なデータ取得、金銭が絡む操作などは、意図確認とセットで止めやすい。
そして最終防波堤が、人間承認である。すべてを承認にすると運用が崩れるので、基準を作る。金銭、個人情報、外部公開、権限変更、データ削除や設定変更のような不可逆操作は、原則承認が妥当だ。逆に、読み取り専用の検索や、社内限定の下書き作成などは自動化しやすい。承認の設計はセキュリティだけでなく業務設計でもあるため、現場の速度とリスクのバランスを明文化しておくと揉めない。
ここまでの要件を一言でまとめるなら、「モデルは提案するだけ、決定と実行はシステムが制御する」になる。エージェントの価値は判断の補助と手順の提案にある。実行の安全性は、別の仕組みで担保する。この役割分担を徹底できるかが勝負だ。
現場で効くアーキテクチャ:分離・制約・人間の関与
要件が分かったとしても、実際にどんな構成にすれば事故が減るのか、という話に落とし込みたい。ここでは、現場で採用しやすい「分離」「制約」「人間の関与」という三つの設計原則でまとめる。
第一の分離は、コンテキストと権限の両方で行う。コンテキストの分離とは、信頼できる指示と、信頼できない外部データを混ぜない設計だ。外部入力をそのまま“命令として扱ってよい領域”に入れない。エージェントが参照する資料やメール本文は「参考情報」として扱い、ツール実行の判断に直接影響しないようにする。具体的には、外部入力を別チャンネルに隔離し、実行前に要約や抽出を通して必要な事実だけを取り出し、命令文や誘導文をそのまま通さない流れにする。完璧ではないが、混ぜっぱなしよりは遥かに安全になる。
権限の分離とは、役割ごとにエージェントを分け、ツール権限も分けることだ。たとえば「問い合わせ分類・要約」だけをするエージェントは読み取り権限だけにし、「返信文の下書き」を作るエージェントも送信権限は持たない。「送信」だけができるコンポーネントを別に置き、そこに承認や検証を集約する。こうすると、もし一つのエージェントが誘導されても、被害は局所化する。ここはセキュリティの鉄則で、エージェントでも同じだ。
第二の制約は、ポリシーで実行を縛ることだ。ツール呼び出しは「許可された操作しかできない」「引数は検証される」「危険操作は二重確認される」という前提にする。加えて、実行環境も制約する。ネットワーク到達先を絞る、ファイルアクセスを限定する、外部送信を遮断する、短命トークンを使うなど、環境側の制約はモデルの挙動に依存しないので強い。エージェントの安全性は、モデルの賢さよりも制約の強さに比例しやすい。
第三の人間の関与は、単なる承認ボタンではなく、運用として設計することが重要だ。承認が必要な操作の基準を定義し、その基準に引っかかった場合は、エージェントが「なぜその操作が必要か」「何を根拠にそう判断したか」「実行すると何が起きるか」を説明した上で承認を求める形にする。ここで説明が弱ければ承認されにくいので、エージェントの提案品質も自然に上がる。逆に、承認者が判断できない粒度で投げてくる設計だと、承認は形骸化して危険になる。
最後に、これらを支えるのが観測性である。どの入力を見て、どのツールをいつ呼び、どんな結果になったかを追跡できるようにする。エージェントは挙動が変わりやすい。モデル更新やプロンプト更新、ツール追加で、昨日まで安全だったものが今日危険になることもある。だからこそ、ログと監査、異常検知の仕組みを最初から組み込むべきだ。ここまでやって初めて、インシデントが起きても原因究明と再発防止が可能になる。
プロンプトインジェクション対策を、プロンプトだけで完結させようとするのは発想が逆である。インジェクションは起きるものだと割り切り、起きても被害が出ないように実行系を守る。境界を引き、ツール実行を検証し、権限を分離し、危険操作には人間の関与を入れ、ログで追えるようにする。AIエージェントを安全にする鍵は、「賢いモデル」ではなく「強い設計」にある。これを押さえれば、エージェントは危険なブラックボックスではなく、統制可能な業務システムとして扱えるようになる。