FlawOpen

flawopen.com/AI Security/mcp-python-sdk-oauth-issuer-confusion

● CWE-345 / CWE-522 · CVSS 7.5[1] · 高
セキュリティ研究 · FlawOpen

MCP Python SDK OAuthのissuer検証不備

GHSA-qx49-fqc8-xw99では、HTTP MCPサーバーが影響を受けるPython SDKのOAuthクライアントが認証情報を送信し得る宛先に影響できました。mcp 1.30.0または2.2.0へ更新し、マシン間認証プロバイダーではissuer=を設定してください。CVEは割り当てられていません。[1], [3], [8]

CVSS ベクトルCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N[1]
💡 わかりやすい解説 (ELI5)

会社が封印した鍵を、承認済みの案内カードに記載された銀行へ郵送するとします。MCPサーバーがそのカードを渡せる状態で、あるフォールバック経路は記載先が想定した銀行か確認しませんでした。Issuer検証は、鍵を送る前にカードの識別情報と設定上の信頼する銀行を照合する仕組みです。[1], [2]

主要な概念と専門用語

MCPクライアント
Model Context Protocolを使い、MCPサーバーのツールやデータに接続するアプリケーションです。この問題はPython SDKをOAuthプロバイダー付きのHTTPクライアントとして使う場合に影響します。[1]
認可サーバーのissuer
トークンを発行するOAuthサービスの安定した識別子です。クライアントは発見したメタデータを独立して想定したissuerと照合する必要があります。[1], [2]
Protected Resource Metadata (PRM)
保護されたリソースの認可サーバーを示すメタデータです。PRMがない場合、SDKには旧来の検出経路もあります。[1], [2]
PKCE code verifier
OAuth認可コードの交換を、フローを開始したクライアントに結び付けるためにクライアントが生成する秘密値です。信頼できないエンドポイントに開示してはいけません。[1], [2]
CWE-345 / CWE-522
データ真正性の検証不足。想定した情報源からのデータであることを十分に確認せず受け入れる弱点です。 CWE-522は認証情報の保護不足を示します。[1], [4], [7]

フレームワーク対応

ステップ・バイ・ステップの攻撃フロー

ステップ 1

HTTP MCPクライアントがOAuth認証情報を保持

アプリケーションは影響を受けるmcpバージョンとSDKのOAuthプロバイダーを使用します。クライアントシークレット、署名鍵、または保存済みクライアント登録を保持したまま、完全には信頼できないMCPサーバーへ接続する場合があります。[1]

ステップ 2

サーバーが認可サーバーの検出に影響

mcp 1.9.1–1.29.1では、すべての検出経路でissuer検証と認証情報のバインドが不足していました。mcp 2.0.0–2.1.1は、PRMがなく旧来のフォールバックを使う場合、または403 insufficient_scope後の追加検出で影響します。両系列とも、マシン間認証プロバイダーには事前設定済み認証情報を結び付けるissuer=がありませんでした。 アドバイザリのパッケージ範囲はプレリリース2.0.0a1から<2.2.0までです。そのため、影響を受ける2.0.0のプレリリース版も対象です。[1], [3], [8]

ステップ 3

トークンエンドポイントに認証情報が送信

クライアントはクライアントシークレット、認可コードとPKCE検証値、または署名済みアサーションを、そのメタデータが選んだエンドポイントへ送る可能性があります。対象となる認証情報はプロバイダーにより異なり、すべてのクライアントが影響を受けるわけではありません。[1], [2]

ステップ 4

影響はプロバイダーと権限に依存

受信者は漏えいした認証情報やトークンを付与済み権限の範囲で利用できる可能性があります。告知では無人プロバイダーをCVSS 7.5、ユーザーがログインを開始する対話型プロバイダーを6.5と評価しています。告知によると、CVEはまだ割り当てられていません。[1]

ステップ 5

Issuer固定で信頼境界を閉じる

修正版は検出前に想定issuerを決め、不一致のメタデータを拒否し、保存済み登録をそのissuerに結び付けます。マシン間認証プロバイダーにも明示的なissuer=が必要です。[1], [2], [3], [8]

MCP Python SDK OAuthのバージョン別対応マトリクス

クライアント構成公表された影響条件必要な対応
mcp 1.9.1–1.29.1を使うHTTP OAuthクライアントすべての検出経路でissuer検証と、認証情報をissuerに一貫して結び付ける処理が不足していました。mcp 1.30.0以降へ更新し、実際にデプロイされたバージョンを確認します。
mcp 2.0.0–2.1.1を使うHTTP OAuthクライアントPRMがなく旧来のフォールバックが動く場合、または403 insufficient_scope後の追加検出で影響します。 アドバイザリのパッケージ範囲はプレリリース2.0.0a1から<2.2.0までです。そのため、影響を受ける2.0.0のプレリリース版も対象です。mcp 2.2.0以降へ更新し、実際にデプロイされたバージョンを確認します。
事前設定済み認証情報を使うClientCredentialsOAuthProviderまたはPrivateKeyJWTOAuthProvider影響バージョンには、認証情報を想定する認可サーバーに結び付けるissuer=設定がありませんでした。更新後にissuer=を明示します。1.xで非推奨のRFC7523OAuthClientProviderから移行します。
SDKで構築したサーバー、stdioクライアント、または独自トークン/ヘッダーを渡すクライアントこのアドバイザリの影響対象ではありません。この問題についての対応は不要です。影響を受けるHTTP OAuthクライアントも使う場合は再評価してください。

根本原因の分析 (Root Cause)

この信頼境界の問題には、関連する 2 つの原因がありました。影響を受ける一部の検出経路では、認可サーバーのメタデータにある issuer を MCP サーバーとは独立して期待される値と一貫して比較しておらず、保存済みまたは事前設定された資格情報も本来の issuer に結び付けられていませんでした。そのため、悪意のある、または侵害された MCP サーバーがトークン交換先を自ら管理するエンドポイントへ誘導し、クライアントが保持する OAuth 情報を受け取る可能性がありました。修正では検出前に期待する issuer を決定し、不一致を拒否して、保存済み登録をその issuer に結び付けます。無人の machine-to-machine プロバイダーでは明示的な issuer= も必要です。[1], [2]

ソースコード比較:脆弱 vs 堅牢化

修正版SDKにはissuer引数があります。マシン間認証情報を正しい認可サーバーに結び付けますが、SDK更新、古い未バインド登録の削除、漏えいした可能性のある認証情報のローテーションの代わりにはなりません。[2], [3], [8]

ソース抜粋: mcp.client.auth

脆弱な実装
import os
from mcp.client.auth import ClientCredentialsOAuthProvider

auth = ClientCredentialsOAuthProvider(
    client_id=os.environ["MCP_CLIENT_ID"],
    client_secret=os.environ["MCP_CLIENT_SECRET"],
)
堅牢化されたセキュアパッチ
import os
from mcp.client.auth import ClientCredentialsOAuthProvider

auth = ClientCredentialsOAuthProvider(
    client_id=os.environ["MCP_CLIENT_ID"],
    client_secret=os.environ["MCP_CLIENT_SECRET"],
    issuer=os.environ["MCP_AUTH_ISSUER"],
)
# mcp >= 1.30.0 (1.x) または >= 2.2.0 (2.x) を使用してください。

エンジニアリング&システム堅牢化チェックリスト

参考資料

← AI Security Directory →