概要

Web検索を禁止すると、エージェントは古い知識だけで戦うことになる。かといって、生のWebをそのまま読ませると、間接プロンプトインジェクションと持ち出しの経路が開く。

この二択を抜けるのが、検索プロキシ という考え方だ。エージェントに「Web」を渡すのではなく、許可された検索・取得の結果だけ を渡す。生のHTMLではなく、構造化されたテキストと出典を渡す。検索クエリも、取得URLも、プロキシ側で検査する。

これは「Web検索を安全にする」というより、「Web検索を、観測可能で制限された一つのサービスにする」 という設計である。


なぜ生のWebが危険か

  • 取得したページの不可視テキスト、メタデータ、コメントに命令を埋め込める
  • 検索クエリやURLに機密を埋め込ませ、外部へ持ち出せる
  • ツール結果として文脈に戻ると、信頼できる情報のように扱われやすい
  • 人間が見ない部分(白文字、1ptフォント、不可視Unicode)をエージェントは読む

OWASPも、外部データはすべてuntrustedとして扱い、取得結果をそのまま信頼しないよう求めている。サニタイズは補助であり、残ったテキストが安全であることを保証しない。


検索プロキシの構成

1. クエリブローカー

エージェントは検索APIを直接叩かず、社内のブローカーにクエリを渡す。ブローカーは、クエリに機密パターンが含まれていないかを検査し、許可された検索バックエンドにだけ転送する。

2. ドメインの許可リスト

検索結果の取得先を、信頼できるドメインに限定する。OpenAIのWeb検索ツールには filters があり、最大100件の allowed_domains / blocked_domains を指定できる。公式ドキュメント、ベンダーのドキュメント、社内Wikiなど、目的別にリストを分ける。

許可リストは「安全」の証明ではない。許可したサイトが侵害されることも、ユーザー生成コンテンツを含むこともある。あくまで 攻撃面を減らす ための制御だ。

3. 取得とサニタイズ

ページを取得したら、モデルに渡す前に洗う。

  • スクリプト、スタイル、隠し要素、不可視文字を除去する
  • HTMLをそのまま渡さず、本文だけを抽出する
  • PDFはテキストとメタデータを分離し、隠しレイヤーを落とす
  • 画像や添付は、必要なら別のCDR(Content Disarm and Reconstruction)を通す

Menlo SecurityのMARSは、まさにこの「エージェントが読む前に洗う」層を商用サービスとして提供している。サンドボックスがマルウェアの挙動を見るのに対し、こちらは コンテンツがエージェントに与える命令 を見る。

4. 構造化して返す

モデルには、生のHTMLではなく、必要なフィールドだけを構造化して返す。タイトル、本文の抜粋、出典URL、取得日時。OWASPも、Webスクレイピングや検索ツールでは、生のHTMLではなく必要な構造化データを抽出するよう求めている。

ただし、構造化されたフィールドの中身もuntrustedである。型が正しいことは、内容が安全であることを意味しない。

5. キャッシュ・オフラインモード

リアルタイム性が不要なら、キャッシュ済みの検索結果だけを使う手もある。OpenAIのWeb検索ツールは external_web_access: false で、ライブのWebアクセスを切ってキャッシュ/インデックスのみにできる。HIPAAの文脈でも、ライブ検索は対象外だが、オフライン/キャッシュのみのモードはZDR対応プロジェクトで対象になりうる。

鮮度は落ちる。だが、外部への新規通信を減らす という意味は大きい。

6. egressプロキシ

取得だけでなく、送信も制御する。StripeのSmokescreenのようなHTTP CONNECTプロキシは、ホスト名の許可リストと、プライベートIP・リンクローカル・クラウドメタデータへの接続ブロックを提供する。MCPのセキュリティガイドでも、SSRF対策としてegressプロキシが推奨されている。

エージェントのコンテナから直接インターネットに出さず、プロキシだけを通す。これで、たとえエージェントが任意のURLを叩こうとしても、許可した宛先以外には出られない。

7. ログとDLP

検索クエリ、取得URL、返した内容、外部へ送ったリクエストを記録する。機密パターンが送信に含まれていないかを検査する。ログは、事故後の調査だけでなく、ポリシーの改善 に使う。


残るリスク

検索プロキシは万能ではない。

  • 可視テキストの意味的な注入 は残る。サニタイズでは、文章として自然な攻撃指示を消せない
  • 許可ドメインの侵害 は防げない。信頼していたサイトが乗っ取られることがある
  • キャッシュの鮮度 は落ちる。古い情報を最新として扱うリスクがある
  • サニタイザーの bypass は起こりうる。完璧なフィルタはない
  • 持ち出し は、検索以外の経路(画像URL、DNS、外部API)でも起こりうる

だから、検索プロキシは単独で使わず、実行権限の最小化・承認ゲート・egress制御 と重ねる。検索は「読む」権限、外部送信は「送る」権限として分離する。


個人開発者向けの最小構成

  • 検索APIのドメインフィルタを使う(公式ドキュメント、RFC、ベンダードキュメントだけ)
  • ブラウザ操作用のエージェントには、専用プロファイル・専用コンテナを使う
  • 機密を扱うセッションでは、検索を切る。公開情報の調査と、機密の分析を同じセッションでやらない
  • 取得したHTMLは、リーダーモードやテキスト抽出を通してから読ませる
  • 可能なら、ローカルの検索プロキシ(SearXNGなど)を立て、そこ経由に固定する。ただし、SearXNGは「安全」ではなく「集約点」として使う
  • curl を許可するなら、プロキシ環境変数を強制し、直接の外部通信を塞ぐ

まとめ

セキュア検索は、モデルに「気をつけて」と言うことではない。検索と取得を、許可・サニタイズ・構造化・ログを持つサービスとして切り出す ことだ。生のWebを渡さない。渡すとしても、何を渡したかを記録する。この境界があれば、Web検索を全面禁止せずに、リスクを測れる形で使い続けられる。


関連ノート


参考資料