Skip to content

response idは秘密情報:共有AIゲートウェイにおけるResponses APIの認可の穴

   
response idは秘密情報:共有AIゲートウェイにおけるResponses APIの認可の穴のGPT生成本文インフォグラフィック

response idは、ただの識別子に見える。
ログにも、URLにも、エラーメッセージにも、気軽に載せてしまう。
APIキーなら決して置かない場所に、平気で現れる。

ところが、共有AIゲートウェイの構成では、そのIDを知っているだけで、他人の会話が読める。
継続もできる。
つまりresponse idは、識別子の顔をした、権限そのものだ。
そして厄介なことに、この穴は公式ドキュメントのどこにも書かれていない。

response idはcapability tokenである

IDだけで会話が読める構造

まず、構造を確かめる。
Responses APIは store: true(デフォルト)で、リクエストとレスポンスをサーバー側に保存する。
保存された会話に対しては、IDだけで二つの操作ができる。

  • GET /responses/{id}:会話全体の取得
  • previous_response_id の指定:会話状態を引き継いだ継続

肝心なのは、認可の粒度だ。
それはリソース単位(APIキーまたはEntraトークン)であって、ユーザー単位ではない。
同じ資格情報でアクセスしているかぎり、誰がリクエストしているのか、そのレスポンスへのアクセス権があるのかを検証する、組み込みの仕組みは存在しない。

共同利用ゲートウェイで認可の穴になる

単一ユーザーの利用なら、この設計は問題にならない。
問題が牙をむくのは、AIゲートウェイで複数のユーザーやチームがバックエンドを共同利用する構成だ。

この構成では、全ユーザーが同一のバックエンド資格情報を共有する
だから、何らかの経路でresponse idを知った他のユーザーは、正規の認証を通したまま、他人の会話を読める。
引き継いで継続もできる。
IDが漏れることが、そのまま会話履歴の漏えいになる。

response idは、推測困難な文字列だ。
だが、APIキーのような機密情報としては扱われにくい。
ログ、URL、エラーメッセージ、デバッグ画面。
APIキーなら決して置かない場所に、平気で現れる。
識別子が所在を運ばない設計の悪さは前に扱ったが、今回は逆向きだ。
識別子が、権限そのものとして機能してしまっている。
「推測不能性だけに依存したcapability token」と捉え直すと、扱いの軽さと権限の重さの非対称が、はっきり見える。

LiteLLMとMicrosoftが独立に同じ結論に至っていた

この穴は、私だけが気づいたものではない。
少なくとも二つの組織が、独立に、同じ場所へ到達していた。

LiteLLM:製品機能として修正済み

LiteLLMは、この問題を2025年10月、セキュリティ修正として対応済みだった。
PR #15757のタイトルが、そのまま状況を語っている。
「Responses API - prevent User A from retrieving User B’s response, if response.id is leaked」。

  • 共有アカウントでのretrieveに対する所有権チェックを実装(参考実装:responses_id_security.py
  • 別チームのサービスアカウント間の相互アクセスも防止
  • デフォルト有効で、管理者がオプトアウト可能

ただし、CVE化や炎上ではない。
静かにPRで直された類だ。
共同利用ゲートウェイでResponses APIのステートフル機能を本格利用する組織がまだ少なく、露出面が顕在化しにくいためだと見ている。

Microsoft:公式ブログは指摘、公式ドキュメントは沈黙

Azure側の認知は、層によって温度差がある。

状況
Microsoft Learn(公式ドキュメント)沈黙。取得・30日保持・削除を淡々と記述し、クロスユーザーアクセスへの警告なし
Microsoft Community Hubブログ問題を明示的に指摘し、解決策を実証(2025年9月)
Microsoft Q&A保存場所・保持期間の懸念のみで、認可の穴は素通り(代表例:回答は「response idを控えておくこと」と助言するのみ)
Azure-Samples/AI-Gateway(30以上のラボ集)response所有権を扱う専用ラボなし

決定的なのは、Healthcare and Life Sciencesブログの記事「Building Secure, Multi-User AI Workflows with the Responses API」(2025年9月)だ。
「Responses APIはデフォルトで、response IDさえあれば任意のレスポンスを取得できる。誰がリクエストしているか、アクセス権があるかを検証する組み込み機構が存在しない」と、明言している。
そのうえで、作成したユーザーだけがretrieve・継続できることをAPIMポリシーで保証するラボを構築し、こう結論づけた。
「モデルを守るだけでなく、レスポンスも守る必要がある」。

対応の非対称

つまり、LiteLLMとMicrosoftは、独立に同じ問題へ到達している。
だが、製品機能化の度合いが違う。

LiteLLMAzure/APIM
問題認識内部チケットとして公式にトラッキング公式ブログで明示、Learnドキュメントは沈黙
対処製品機能としてデフォルト有効DIYポリシーパターンの提示のみ
位置づけセキュリティ修正ベストプラクティス・ラボ

そして、いちばん怖いのは、この一点だ。
公式ドキュメントに載っていない以上、APIMでAIゲートウェイを構築する組織の大半は、この穴に気づかないまま、Responses APIを開放する可能性が高い。

ゲートウェイ側での対策

3つの選択肢

では、ゲートウェイ側で何ができるのか。
対策は、大きく三つだ。

  • store: false の強制。APIMポリシーでリクエストボディを書き換える。単純だが、ステートフル機能そのものを放棄することになる
  • ゲートウェイ側での所有権マッピング。作成時に「ユーザーID → response id」の対応を記録し、取得・継続時に所有チェックを行う。LiteLLMの修正もMicrosoftブログのラボも、このアプローチだ
  • テナント分離。ユーザーやチームごとにバックエンドの資格情報を分ける。確実だが、コストと運用が重い

ステートフル機能を活かしつつ守るなら、本命は所有権マッピングになる。

APIMでのDIY実装の注意点

その所有権マッピングを、APIMポリシーで実装するとしよう。
作成時に所有者IDを保存し、取得・継続時に照合して、不一致なら403を返す。
理屈は単純だ。
だが、ここで一つ、置き場所の問題が立ちはだかる。

APIMの組み込みキャッシュは、揮発性でリージョン独立だ。
Responses APIの保持期間である30日をまたぐマッピングの保存には、使えない。
RedisやCosmos DBのような外部ストアが要る。
APIMポリシー単体では状態管理が苦手なので、状態を扱う処理は、APIMとバックエンドの間に置くプロキシ層へ寄せる構成が自然になる。

ここに、もっと大きな前提の崩れがある。
ステートフルなAPIをゲートウェイで守るには、ゲートウェイ側も状態を持たざるを得ない。
「リクエストが通過する瞬間に、すべてを検査すればよい」。
従来のゲートウェイが立っていた、この前提が崩れている。
冒頭の、ログに気軽に載るIDに戻る。
それが権限を運んでしまう世界では、守るべき境界は通過点ではなく、状態のほうへ移っている。

関連記事

  1. APIM AI GatewayのResponses API対応マトリクス:ステートレスな部分だけが進む理由
  2. マネーフォワード事案から考えるSaaS依存とゼロトラストの設計思想
  3. そのIDは鍵であって住所ではない:識別子が所在を運ばない設計の悪さ
  4. AIで賢くなるほど、組織はバラバラになる:共通認識を「転送」から「再生成」へ
  5. 一人でも失敗したら終わる世界で、人類はどう生き残るか
  6. なぜGmailには個人情報を入れるのにAIには入れないのか
  7. HTMLの有効性とエージェント出力の情報設計