
2026/11/07 7:50
ChatGPT がコンネクター間でデータを静かにやり取りし、賞金稼ぎが身分証明書を狙っています。
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
2026 年 11 月 5 日、重大なセキュリティ欠陥により、ChatGPT はフォローアップツール呼び出しを不正なコンネクター経由で静かにルーティングし、ユーザーの安全性境界を迂回しました。この問題は、単一のユーザーアカウントが別々のコンネクター(Connector A(開発者モード)および Connector B(アプリディレクトリ))を同じ MCP サーバーにリンクさせたときに発生しました。バックエンドは共有されていますが、各コンネクターには独自の OAuth クライアントが存在しており、動作中にこれら異なる信頼領域が誤って統合されました。
この脆弱性は、セキュリティ境界が基盤となるサーバー URL ではなく、特定のコンネクター ID とその OAuth クライアントによって定義されたために現れました。アクションに対するユーザー確認は Connector A のウィジェット経由で生成されましたが、フォローアップ呼び出しが Connector B を介してルーティングされると、これらのコードを元のクライアントを検証せずに受け入れます。したがって、機密データが明示的なユーザー同意なしにアプリケーション間を流動くすることができます。コンネクターが同じプロバイダーまたは MCP サーバー URL を共有しても、URL だけに依存すると危険な脆弱性が発生するため、セキュリティは特定のコンネクターとその独自の OAuth クライアントに厳密に紐付ける必要があります。この行動により、共有エンドポイントにもかかわらず、別々の OAuth グラントを有するアプリケーション間で不正なデータ転送が可能になります。
本文
MCP コネクター切り替えによる認証境界侵害リスクと対応事例
概要
2 つのコネクター(連携ツール)が同時に有効化された会話において、ChatGPT がフローを開始したコネクターとは異なる別のコネクターを使ってフォローアップのツールコールを実行しました。
- ユーザーにはこの切り替えについて一切通知されませんでした。
- 実行されたコールには、最初のコネクターから発行されたワンタイム確認コードが含まれていました。
環境設定
以下の条件が再現されています:
- 1 つの ChatGPT アカウントで、同一の MCP サーバーに接続する 2 つのコネクターが有効化。
- コネクター A:開発者モードで追加されたカスタムコネクター。
- コネクター B:アプリディレクトリから公開されている標準アプリ。
- 両コネクターは独立した OAuth クライアントを持ち、サーバー側では同一ユーザーに対して2 つの異なるクライアントとして認識されています。
問題発生手順
- 両コネクターが有効化された会話において、ユーザーの確認が必要なアクションをリクエストする。
- モデルは確認ツールをコールし、コネクター A を通じて MCP Apps ウィジェットを表示。ユーザーが承認すると、ウィジェットからワンタイム確認コードが
経由で会話に送信される。ui/message - モデルはそのコードを使用してフォローアップコールを実行する際、静かに(silenciously)コネクター A を回避し、コネクター B を経由させる処理が行われる。
結果とサーバー側の挙動
- サーバーはコールを拒否。これは確認コードがコネクター A の OAuth クライアントにバインドされているためです。
- コードの詳細なログ分析から、以下の手順で試みが行われたことが判明:
- 確認コードは コネクター A 経由で承認(確認)された。
- 同コードが コネクター B 経由で換金(redeem)を試みた。
- ユーザーには切り替えの事実は告知されず、この試みはすべて失敗した。
なぜこれが問題なのか
- ユーザーはコネクター A でフローを開始し、同ウィジェットで承認を行うが、フォローアップコールは知らぬうちにコネクター B へルーティングされる。
- 各コネクターは独立した OAuth グラントを持つため、この「静かな切り替え」はユーザーの同意を得ずにアプリ間をデータが横断する状態を招く。
- 今回のケースでは両コネクターが同一プロバイダーのためサーバーでブロックされたが、サードパーティのコネクターも有効化されている場合、「静かな切り替え」によってアプリのデータが別のプロバイダーへ渡される可能性は依然存在する。
- 共有されている MCP URL だけで 2 つのコネクターを同一のものとして扱うことはできない。URL ではなく、独立した OAuth クライアントを持つコネクターそのものが境界線となる。
期待される動作(正しい実装)
- ツールコールは MCP サーバーの URL ではなく、OAuth クライアントに基づいてコネクターに紐付ける必要がある。
- フォローアップコールは、フローを開始した同じコネクターおよび OAuth クライアントを経由すべきである。
AldiPower 様への謝辞と分析
事例の共有へのご礼
AldiPower 様にはご明確な事例の共有をいただき感謝申し上げます。特に以下の点が重要です:
- ツール選択と認証継続性の区別についてご指摘いただいた点。
- サーバー側の保護措置が機能し、コネクター A の OAuth クライアントにバインドされた確認コードに対して、コネクター B からの換金試行が拒否された事実。
残される懸念とアーキテクチャ上の要件
しかし、コールの拒否自体が根本的な問題を解消するものではありません。ユーザーに知らせず別の経路をたどられる事実は看過できません。 より健全なアプローチとして以下が必要です:
- 待機中の処理および承認を、元のコネクターおよび検証済みの OAuth グラントにバインドする。
- 承認または実行中の状態で、自動的なコネクター切り替えを禁止する。
- コネクターを変更する必要がある場合は、明示的なユーザーの同意を求める。
- サーバー側で、短期有効な確認コードが意図された操作、クライアントアイデンティティ、および認証コンテキストと一致するか厳密に検証する。
- 機密となる情報を晒さずに、コネクタールート決定を診断トレース(diagnostic traces)に記録する。
責任の分離について
- MCP サーバー:認証の実行を担当。
- クライアントサイドのオーケストレーション層:ワークフローで選択されたコネクターの保持を担当すべき。
根本原因の特定に向けた問いかけ
トラース(Trace)の確認結果次第で原因が異なります:
- 承認処理中にコネクターアイデンティティが変更されたのか?
- それとも、モデルがフォローアップツールのコールを選択した際に変更されたのか?
認証境界に関わるため、公的議論のみに依存するだけでは不十分です。技術的証拠を提出し、**OpenAI の「協調的な脆弱性情報開示プロセス(CVD)」**を通じて報告することを強くお勧めします。
追記:バグ Bounty プログラムへの対応状況
個人が OpenAI のバグ Bounty プログラム経由で報告しようと試みました。しかし、以下の理由によりレポート提出を断念しました:
- レポート提出前に、生物認証情報や身分証明書の個人データを提供することを要求された。
- 第三者に対して、何もしない段階でこれらを提供するのは許容しがたい。
したがって、バグ Bounty プログラムへの報告は行いませんでした。