MCPの公式Python SDKに、エージェントのOAuth資格情報を悪意あるMCPサーバーに渡してしまう欠陥があった。SDKのメンテナーが9月28日にセキュリティアドバイザリ GHSA-qx49-fqc8-xw99を公開した。深刻度はCVSS 7.5である。見つけたのはセキュリティ企業Cycodeの研究者で、同社はブログで攻撃の流れを説明している。報道ではThe Hacker NewsとCybersecurity Newsが伝えた。
この件で分かったのは、OAuthを入れたことと資格情報を守れることは別だ、という点である。ログインもユーザーの同意も本物の画面で行われる。それでも、トークンの送り先を接続先のサーバーが決められるなら、OAuthを入れた意味はなくなる。
穴は、送り先を接続先のサーバーに決めさせていたこと
アドバイザリは、問題を次のように書いている。
the SDK's OAuth client support let the MCP server a client connected to decide where the client's OAuth credentials were sent
訳: SDKのOAuthクライアント機能では、クライアントのOAuth資格情報をどこへ送るかを、接続先のMCPサーバーが決められる状態になっていた
エージェントがOAuthで守られたMCPサーバーにつなぐと、クライアントはまずそのサーバーから案内を受け取る。どの認可サーバーで認証すればよいか、を示すメタデータである。クライアントはその案内をもとに、ログイン画面のURLや、認可コードをトークンに引き換える先を知る。アドバイザリが指摘するのは、この案内をSDKが確かめずに使っていたことだ。接続先のMCPサーバーに悪意があれば、資格情報の行き先を自分のところへ向けられた。
OAuthの仕組みが破られたわけではない。認可サーバーは本物で、ユーザーの認証も本物で、発行されるトークンも本物である。差し替えられたのは、手に入れた資格情報をクライアントがどこへ持っていくか、という一点だけだった。
ログイン画面が本物なので、見抜けない
この攻撃が厄介なのは、利用者が見る画面に怪しいところがないことである。Cycodeの研究者 Yuval Elbar は9月29日にこう説明している。
You get redirected to the real Google/Okta/Azure AD page. It's not a phishing page... You approve it because there's nothing wrong with it.
訳: 飛ばされる先は本物のGoogle/Okta/Azure ADのページだ。フィッシングのページではない……おかしなところが何も無いから、承認してしまう。
これまでのフィッシング対策は、URLが本物か、画面が本物かを確かめるよう利用者に求めてきた。今回の攻撃では、その確認がすべて正しい答えを返す。利用者は本物の画面で本物のアカウントに同意しており、その後で資格情報がどこへ流れるかは画面に出てこない。人間による承認を挟んでも、承認する本人が見られない場所で攻撃が起きていれば、歯止めにならない。
エージェントの場合、被害はさらに大きくなる。MCPのクライアントは、多くのサーバーに次々つなぐのが普通である。社内のツール、SaaSのコネクタ、開発者が試しに入れた見知らぬサーバーが、同じハーネスの中に並ぶ。その中に悪意あるものが1つあれば、利用者が別の正規のサービスのために本物の画面で通した同意が、そのまま攻撃者の手に渡りうる。最初は普通に動き、後から案内を書き換えるRug Pull型のサーバーなら、導入時の審査もすり抜ける。
守るのに要るのは、issuerの検証と資格情報の紐付け
そこで、送り先を決める権限を接続先のサーバーから取り上げる必要がある。要るのは2つだ。
1つ目はissuerの検証である。認可サーバーのメタデータには、発行元を示すissuerが入っている。クライアントは、そのissuerが自分の期待する認可サーバーと一致するかを確かめる。食い違えば、案内に従わずに止める。
2つ目は資格情報の紐付けである。認可コード、トークン、クライアントの秘密は、発行した認可サーバーに結び付けて扱う。別の宛先から求められても渡さない。こうすれば、接続先のMCPサーバーが案内を書き換えても、資格情報の行き先は変わらない。
どちらもOAuthの新しい機能ではない。メタデータを使う標準の手順に書かれている確認を、SDKがきちんと行うかどうかの話である。公式SDKにこの確認がなかったことは、MCPのOAuth対応が、まず動くことを優先して広まったことを示している。
使う側が今すべきこと
MCP Python SDKを使ってOAuthでMCPサーバーにつないでいるなら、アドバイザリに書かれた修正版に上げることが先である。そのうえで、見直しておきたい点が3つある。信頼できないMCPサーバーにつないだことがあるか。そのとき、どの認可サーバーの資格情報が使われたか。必要ならトークンを失効させ、クライアントの秘密を作り直す。Python以外のSDKや自作のクライアントも、同じ確認をしているかを点検したい。
今回の欠陥は、エージェントの安全を「OAuthに対応しているか」で測る見方の限界を示した。問うべきなのは、トークンの送り先を誰が決めているかである。それが接続先のサーバーである限り、ログイン画面がどれほど本物でも、資格情報は守られていない。




