外部コンテンツを介した間接的なプロンプトインジェクション

外部コンテンツを介した間接的なプロンプトインジェクション

説明

間接的なプロンプトインジェクションは、攻撃者がWebページや文書などに指示を埋め込み、アプリケーションがそのコンテンツをモデルのコンテキストに取り込むことで発生します。モデルがデータと指示を十分に区別できないと、埋め込まれた文が本来のタスクや後続の操作を変える可能性があります。

影響は、モデルがアクセスできる秘密情報・ツール・権限と、出力の利用方法に大きく左右されます。外部コンテンツを変更できる主体と、モデルの権限の境界を併せて確認してください。

想定される影響

  • 要約、分類、推薦の結果の改ざん
  • モデルが秘密情報や外部ツールを利用できる場合の、情報漏えいや不正な操作
  • 出力をコマンド、コード、承認、セキュリティ判断に使う場合の、完全性や可用性への影響の拡大

対処方法

あらゆる状況でプロンプトインジェクションを安全に除去できる汎用の文字列サニタイザーはありません。区切り文字、役割の分離、エンコード、RAG、ファインチューニング、外部の指示を無視するよう求める指示は、完全な防御ではありません。

  1. 信頼境界を維持してください。 出所とコンテンツの種類を記録し、不要な取得元、サイズ、形式を制限してください。許可リスト内のドメインでも応答本文を無条件に信頼しないでください。
  2. アクセスを最小限にしてください。 必要なツールとデータだけを提供し、秘密情報や副作用のある操作からモデルを隔離してください。
  3. 認可をモデルの外で行ってください。 決定論的なコードで厳密なスキーマと許可リストを使い、ツールの引数や送信先を検証してください。高リスクな操作にはユーザーの確認を求めてください。
  4. 出力を制限して検証してください。 可能なら構造化された出力や有限の選択肢を使い、後続の処理前に検証してください。スキーマが確認するのは構造であり、意味上の安全性ではありません。値と認可を別途確認し、モデル出力だけでコマンド実行やセキュリティ判断を行わないでください。
  5. 攻撃を繰り返し評価してください。 モデルやプロンプトの変更時に間接的な注入のシナリオを再評価し、入出力とツール呼び出しを監視してください。

例

変更前

javascript
const express = require("express");
const { fetch } = require("undici");
const { streamText } = require("ai");
const { openai } = require("@ai-sdk/openai");
const app = express();

app.post("/bad1", async (_req, res) => {
  const retrieved = await (
    await fetch("https://example.com/manual")
  ).text();
  await streamText({
    model: openai("gpt-5.6"),
    prompt: "Summarize this document:\n" + retrieved
  });
  res.send("ok");
});

変更後

javascript
const express = require("express");
const { streamText } = require("ai");
const { openai } = require("@ai-sdk/openai");
const app = express();

app.post("/good", async (_req, res) => {
  await streamText({
    model: openai("gpt-5.6"),
    prompt: "Summarize this internal FAQ: Support is available Monday through Friday."
  });
  res.send("ok");
});

説明:

  • 変更前: 外部文書の本文がモデルへの入力に含まれます。攻撃者が文書を変更できると、隠した指示で要約に影響を与える可能性があります。
  • 変更後: サーバー側で作成した固定のFAQ本文だけを渡します。外部コンテンツが必要な場合は、上記の多層の対策で影響を抑えてください。区切り文字を加えるだけで、これと同等の保護にはなりません。

参考資料