MCPサーバーとクライアントを作る公式ライブラリ「MCP TypeScript SDK」で、2026年10月に7件の脆弱性が公表されました。10月20日には5件がまとめて出ており、最も高いCVE-2026-111767はCVSS 8.6です。修正版は1.x系が@modelcontextprotocol/sdk 1.32.0、2.x系が@modelcontextprotocol/serverとclientの2.3.0です。ただし3件は版を上げただけでは塞がらず、コードか設定の変更が要ります。本記事では、7件の対象版と修正版、自社のMCPサーバーやクライアントが当てはまるかを確かめるコマンド、更新後に足す設定をTypeScriptのコードで示します。記載内容の根拠は、2026年10月28日時点で確認できる公開情報です。
まとめ:1.32.0・2.3.0へ上げ、さらに設定を3か所足して初めて塞がる
HTTPで公開しているMCPサーバーは、1.x系なら1.32.0以上、2.x系ならserver 2.3.0以上へ上げてください。@modelcontextprotocol/expressを使っていれば2.0.2以上も必要です。2026年10月28日時点のnpmの最新は、1.x系が1.32.2、2.x系のserverとclientが2.4.0でした。
更新だけで終わらないのは3件です。入力の要素数の上限(CVE-2026-111768)とトークンの宛先の検証(CVE-2026-111771)は、修正版で追加された設定が既定で無効のため、自分で有効にします。2.x系の共有インスタンスの混線(CVE-2026-111770)は、修正版が共有を拒むため、コードを直さずに上げると要求が失敗します。
急ぐべきは、複数の利用者がHTTPで接続できるサーバーと、信頼できないMCPサーバーへ接続するクライアントです。
2026年10月公表のMCP TypeScript SDKの脆弱性7件の対象版と修正版
7件はすべてmodelcontextprotocol/typescript-sdkのリポジトリでGitHub Security Advisoryとして公表されています。最初に全体を表で見渡し、そのあとで版の系統ごとの違いを整理します。
CVSSの高い順に並べたGHSA 7件の対象パッケージと修正版の一覧表
表の修正版は、勧告が「この版以上へ上げる」と案内している最初の版です。2.x系はパッケージが分かれているため、使っているものすべてを確かめます。
| 識別番号 | CVSS | 内容 | 1.x系の修正版 | 2.x系の修正版 |
|---|---|---|---|---|
| CVE-2026-111767 | 8.6 | タスクの持ち主を確かめない | sdk 1.32.0 | 対象外 |
| CVE-2026-111770 | 7.7 | 別の利用者へ応答が届く | 対象外 | server 2.3.0 |
| CVE-2026-111768 | 7.5 | 1回の要求でメモリ枯渇 | sdk 1.32.0 | server 2.3.0 |
| CVE-2026-104850 | 7.5 | OAuthの秘密を別の認可先へ送る | sdk 1.31.0 | client 2.2.0 |
| GHSA-f897-62hf-6gxq | 7.5 | 本文サイズと一括送信の上限なし | sdk 1.30.1 | server 2.1.0ほか |
| CVE-2026-111771 | 6.8 | 別サービス向けトークンを受理 | sdk 1.32.0 | server 2.3.0ほか |
| CVE-2026-111769 | 6.5 | 別オリジンへのリダイレクト追従 | sdk 1.32.0 | client 2.3.0 |
CVSSはGitHub Advisory Databaseに載るCVSS v3.1の値です。GHSA-f897-62hf-6gxqは10月27日の公表で、28日時点ではCVE番号が付いていません。どの番号もリリースの順と公表の順が一致しないので、実際の判定は表の版で行います。CVSSの読み方の基礎は脆弱性とは?種類・CVE/CVSSの仕組みと発見から修正までの実務で確認できます。
修正版の公開が10月2日で勧告が10月20日という18日の差の読み方
修正を含む1.32.0とv2.3.0は、2026年10月2日にnpmへ公開されました。勧告の公開はその18日後の10月20日で、GHSA-f897-62hf-6gxqは修正版1.30.1の公開(9月23日)から勧告まで1か月以上空きました。
DependabotやRenovateのセキュリティ更新は、勧告がGitHub Advisory Databaseに載ってから動きます。10月上旬に通常の更新で1.32.0へ上げていれば修正は入っていますが、後述する設定変更は別の作業として残ります。
1.x系のsdkと2.x系の分割パッケージで影響範囲が異なる3つの例
1.x系は@modelcontextprotocol/sdkの1パッケージで、2.x系はserver・client・coreと、express・hono・nodeなどのアダプタに分かれています。分割の経緯はMCP TypeScript SDK v2とは?パッケージ分割とステートレス化の移行要点で解説しています。
CVE-2026-111767は1.x系だけの問題で、2.x系は対象外です。CVE-2026-111770は逆に2.x系のserverだけが対象で、1.x系は2月のCVE-2026-25536の修正(1.26.0)で同じ穴が塞がっています。CVE-2026-111771は2.x系でexpress 2.0.2とserver-legacy 2.3.1も必要で、「serverだけ上げた」状態が起きやすい点に注意してください。
サーバー側の脆弱性4件:セッション混線・メモリ枯渇・トークン誤受理の条件
サーバー側の4件は、いずれもHTTPで接続を受けるサーバーが対象で、stdioだけのサーバーは影響を受けません。
CVE-2026-111767:taskStoreを渡す1.x系サーバーの条件
GHSA-22jm-h49p-29qwによると、実験的なタスク機能のtaskStoreが、どのセッションがタスクを作ったかを確かめていませんでした。1つのInMemoryTaskStoreを共有する利用者どうしが、互いのタスクを一覧し、読み、取り消せた状態です。
対象は、HTTPのサーバーでMcpServerまたはServerにtaskStoreを渡している場合だけです。勧告は、ソースをtaskstoreで検索して何も出なければ対象外と案内しています。実験的なタスク機能は非推奨で、MCP仕様2026-07-28版で作り直されたMCP Tasks拡張に置き換わりました。1.32.0へ上げるか、すぐに上げられなければtaskStoreを外すか、セッションごとに作り分けます。
CVE-2026-111770:共有インスタンスで別の利用者へ応答が混ざる仕組み
GHSA-jm63-cq47-j5jpは、ある利用者への応答や通知が別の利用者へ届く問題です。SDKはメッセージをJSON-RPCのidだけで接続に結び付けていました。SDKのクライアントは要求の番号を0から振るため、通常の使い方でも番号は衝突します。
条件は、複数の利用者がHTTPで接続でき、サーバーやトランスポートを起動時に1回だけ作って使い回していることです。勧告によると、修正前はexpressやhonoなど各アダプタのREADMEの例がこの書き方で、写して作ったサーバーは当てはまりやすい状態でした。1.x系でも2026年2月に同種のCVE-2026-25536(1.10.0〜1.25.3が対象)が出ており、2回続けて同じ使い方が問題になっています。
CVE-2026-111768:4MiB以内の1要求でメモリが尽きる条件
GHSA-46jr-4wx8-v453(CVE-2026-111768)では、ツールの引数に含まれる配列の要素やオブジェクトのキーの数に上限がありませんでした。既定の本文上限4MiBに収まる1回の要求で、プロセスがJavaScript heap out of memoryで落ちます。認証より前にSDKへ要求が届く構成なら、資格情報も不要です。
10月27日のGHSA-f897-62hf-6gxqは、その手前の本文サイズとJSON-RPCの一括送信(バッチ)の件数に上限が無かった問題です。修正後は4MiBを超える本文に413、100件を超えるバッチに400を返します。勧告が示す注意点は、express.json()のような本文パーサーを置いても、バッチの件数は制限されないことです。どちらもツールの入力に配列やレコードを持つサーバーほど影響が大きくなります。
CVE-2026-111771:別サービス向けのトークンをaud未検証で受理
GHSA-rvq5-wwqv-78pqは、サーバー側のBearer認証に、トークンが自分宛てに発行されたか(audience)を確かめる手段が無かった問題です。1つの認可サーバーが複数のサービスへトークンを発行している環境では、別サービス向けの正規のトークンでMCPサーバーに入れました。
対象は、requireBearerAuth()かverifyBearerToken()を使い、自前のverifyAccessToken()でaudを見ていない場合です。MCP仕様のAuthorizationは、サーバーがトークンの宛先をRFC 8707に沿って検証することを必須(MUST)にしています。社内の認可サーバーを複数システムで共有している会社ほど、この条件に当てはまる構成です。トークン検証の設計全般はAPI不正アクセス対策の実装手順で扱っています。
クライアント側の脆弱性2件:OAuthの秘密とAPIキーが外へ出る経路
クライアント側の2件は、自社のアプリやエージェントが外部のMCPサーバーへHTTPで接続する場合が対象です。
CVE-2026-104850:MCPサーバーが指定した認可サーバーへ秘密を送る問題
10月6日のGHSA-6qxp-vccf-f47hでは、SDKのOAuthクライアントが、接続先のMCPサーバーの指定する認可サーバーへそのまま資格情報を送っていました。悪意のあるMCPサーバーが自分の認可サーバーを名乗れば、以前のサインインで保存したrefresh_tokenやclient_secretが、利用者の操作なしに渡ります。
修正版は1.x系が1.31.0、2.x系がclient 2.2.0で、保存する資格情報に認可サーバーのissuerを記録し、別の認可サーバーへは送らなくなりました。ClientCredentialsProviderやPrivateKeyJwtProviderなど同梱のプロバイダは、expectedIssuerを渡さない限り修正後も以前と同じ動作です。認可サーバーの仕組みと、クライアント登録の新方式はCIMD(Client ID Metadata Documents)とはで詳しく説明しています。
CVE-2026-111769:307転送で秘密が別オリジンへ届く経路
GHSA-6prh-2h8m-c8cwは、HTTPのクライアントトランスポートとOAuthの要求が、どのオリジンへのリダイレクトにも従っていた問題です。転送先にはX-API-Keyのような独自ヘッダとmcp-session-idが届き、307か308のときはrefresh_tokenやclient_secretを含む本文まで届きました。Authorizationヘッダは現行のランタイムのfetchが別オリジンで落とします。
1.x系は1.31.0までの全版が対象です。修正後は同じオリジン内のリダイレクトにしか従わず、redirectPolicy: 'follow'を指定すると以前の動作に戻ります。勧告は、管理外のホストへリダイレクトされた可能性があるなら、保持していたAPIキーとclient_secretを入れ替え、トークンを失効させるよう案内しています。
自社のMCPサーバー・クライアントが対象かをnpm lsとgrepで判定する手順
判定に必要なのは、入っている版と問題の機能の使用有無の2点で、どちらもリポジトリだけで確かめられます。
npm lsで@modelcontextprotocol配下の全パッケージの版の読み方
package.jsonの"^1.25.0"は範囲の指定で、実際の版ではありません。ロックファイルが解決した版を、間接依存まで含めて表示します。
# 1.x 系と 2.x 系の両方を、間接依存まで含めて表示する
npm ls @modelcontextprotocol/sdk @modelcontextprotocol/server \
@modelcontextprotocol/client @modelcontextprotocol/express \
@modelcontextprotocol/node @modelcontextprotocol/hono --all
# pnpm の場合
pnpm why @modelcontextprotocol/sdk
# 系列ごとの最新を確かめる
npm view @modelcontextprotocol/sdk dist-tags
npm view @modelcontextprotocol/server version
npxで起動する外部のMCPサーバーにもSDKが含まれるため、社内で配っているサーバーのパッケージも個別に確かめてください。
taskStoreやrequireBearerAuthの使用箇所を洗い出すgrep
勧告が条件に挙げる名前をまとめて検索します。
# サーバー側:タスク機能・Bearer 認証・トランスポートの作り方
grep -rniE "taskStore|requireBearerAuth|verifyBearerToken|StreamableHTTPServerTransport|createMcpHandler" \
--include=*.ts --include=*.js --exclude-dir=node_modules .
# クライアント側:HTTP トランスポートと OAuth の呼び出し
grep -rniE "StreamableHTTPClientTransport|SSEClientTransport|authProvider|withOAuth|fetchToken" \
--include=*.ts --include=*.js --exclude-dir=node_modules .
StreamableHTTPServerTransportやnew McpServerが、リクエストを処理する関数の外(モジュールの最上位や起動処理)にあれば、共有インスタンスの条件に当たります。requireBearerAuthが出たら、verifyAccessToken()でaudを見ているかを読みます。
修正版へ上げた後に要る3つの設定変更をTypeScriptのコードで実装
例は1.x系の@modelcontextprotocol/sdk 1.32系とExpressの組み合わせで書いています。2.x系でも考え方は同じで、勧告はcreateMcpHandler()に毎回新しいサーバーを作る関数を渡す書き方を案内しています。
McpServerとトランスポートをリクエストごとに作る形への書き換え例
共有インスタンスの問題は、要求ごと(またはセッションごと)にサーバーとトランスポートを作れば、修正前の版でも塞がります。2.x系は修正版で共有そのものが拒まれ、2回目のconnect()がALREADY_CONNECTEDで失敗するので、更新より先にこの形へ直しておきます。
import express from "express";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
const app = express();
app.use(express.json({ limit: "256kb" }));
// 要求ごとに新しいサーバーを作る(起動時に1回だけ作らない)
function buildServer() {
const server = new McpServer({ name: "example-server", version: "1.0.0" });
// server.registerTool(...) でツールを登録する
return server;
}
app.post("/mcp", async (req, res) => {
const server = buildServer();
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
res.on("close", () => {
transport.close();
server.close();
});
await server.connect(transport);
await transport.handleRequest(req, res, req.body);
});
app.listen(3000);
セッションを使うサーバーなら、sessionIdGeneratorを設定し、セッションごとにサーバーとトランスポートを1組ずつ持たせます。
maxToolInputElementsと本文サイズで入力の上限を決める設定
CVE-2026-111768の勧告は「更新だけでは何も変わらない」と明記し、2つの設定を求めています。1つはツールの引数の要素数の上限maxToolInputElementsで、既定は無制限です。もう1つは本文サイズの上限で、ツールが本当に必要とする大きさまで下げます。
// ツールの引数に含まれる配列の要素とキーの合計の上限(既定は無制限)
const server = new McpServer(
{ name: "example-server", version: "1.0.0" },
{ maxToolInputElements: 10_000 }
);
// 本文を自分で読ませる場合は、トランスポートに上限(バイト)を渡す
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined,
maxRequestBodySize: 256 * 1024,
});
// express.json() で先に解析する場合は、パーサー側の limit が上限になる
app.use(express.json({ limit: "256kb" }));
1.32.2のソースを読むと、maxRequestBodySizeは解析済みの本文(req.body)を渡したときには適用されません。前の例のようにexpress.json()を使う構成では、パーサーのlimitを必ず設定してください。すぐに更新できない場合は、リバースプロキシで本文サイズを制限するのが勧告の示す回避策です。
expectedResourceでトークンの宛先を確かめる実装
CVE-2026-111771も既定で無効の設定を有効にします。勧告によると、expectedResourceの指定と、verifyAccessToken()がresourceを返す変更を同時に入れる必要があり、片方だけだと全要求が401になります。
import { requireBearerAuth } from "@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js";
const verifier = {
async verifyAccessToken(token: string) {
// verifyJwt は署名と有効期限を検証する自前の関数
const claims = await verifyJwt(token);
return {
token,
clientId: claims.client_id,
scopes: (claims.scope ?? "").split(" "),
expiresAt: claims.exp,
// トークンの aud を resource として返す(URL 型)
resource: new URL(claims.aud),
};
},
};
app.use(
"/mcp",
requireBearerAuth({
verifier,
// 認可サーバーがこのサーバー向けトークンの aud に入れる値
expectedResource: new URL("https://mcp.example.com/mcp"),
})
);
別サービス向けのトークンは、これで401になります。audが配列で届く認可サーバーでは、自社のサーバーのURLを含む要素を選んで返してください。更新前の版では、verifyAccessToken()の中でaudが自社のサーバーを含まないトークンを拒否すれば、どの版でも同じ効果が得られます。クライアント側の2件は、同梱プロバイダへのexpectedIssuerの指定と、更新前ならリダイレクトを拒むfetch(redirect: 'error')を渡す対応で足ります。
HTTPで公開するMCPサーバーを更新で済ませるか設計から見直すかの判断基準
7件の問題は、認可・入力上限・インスタンスの持ち方というMCPサーバーの設計そのものに集中しています。
stdioだけの社内ツールは通常の依存更新の周期で足りるという線引き
Claude DesktopやIDEから子プロセスとして起動するstdioのMCPサーバーは、サーバー側の4件とGHSA-f897のいずれも対象外です。この構成では利用者が1人で、ネットワークからの要求も受け付けません。そのため、次の通常の依存更新で1.32.2以上か2.4.0以上へ上げれば十分で、当日中の対応は過剰です。
例外は、stdioのサーバーの中からHTTPで外部のMCPサーバーや認可サーバーへ接続している場合です。クライアント側の2件の条件に入るため、外部APIのclient_secretを持つなら更新を早めます。MCPの全体像はMCPとは?AIと外部ツールをつなぐ標準規格で整理しています。
複数の利用者へHTTPで公開するサーバーは認可と上限の設計から直す条件
社外の取引先や複数部署の利用者がHTTPで接続するMCPサーバーは、更新だけでは終えないでください。今回の7件のうち3件は設定を足さないと塞がらず、2件(CVE-2026-25536とCVE-2026-111770)は同じ使い回しの書き方が2回続けて問題になりました。READMEの例を出発点に作ったサーバーは、インスタンスの持ち方・トークンの宛先の検証・入力の上限の3点を、勧告と照らして1つずつ確かめる必要があります。
ツールの数が多く、どの入口でどの認可が効いているかを社内で説明できない場合は、外部の診断で抜けを洗い出すほうが早く終わります。一創の脆弱性診断・セキュリティ診断では、MCPサーバーを含むWeb APIの認可と入力検証を点検しています。
MCP TypeScript SDKの脆弱性対応でよく受ける質問と回答
MCP TypeScript SDKの7件の対応について、現場で出やすい疑問をまとめました。
悪用は確認されていますか?更新はどのくらい急ぐべきですか?
2026年10月28日時点で、7件の勧告に悪用の記載はありません。急ぐかどうかは公開範囲で決まります。インターネットや社外から到達できるHTTPのMCPサーバーは、メモリ枯渇の2件が認証なしで成立しうるため、当日中に更新と上限の設定を入れてください。stdioだけのサーバーは通常の更新周期で足ります。信頼できないMCPサーバーへ接続するクライアントは、その中間として週内の更新を目安にします。
1.x系のまま使い続けても修正は受けられますか?
受けられます。今回の修正は1.x系にも1.32.0として出ており、10月23日には1.32.2が公開されました。2.x系への移行を脆弱性対応と同時に進めると、不具合の原因を切り分けにくくなります。まず1.x系の中で上げて設定を足し、移行は別の計画にするのが安全です。移行の作業量はMCP TypeScript SDK v2の移行要点で見積もれます。
更新したらリクエストが失敗するようになったのはなぜですか?
原因は3つ考えられます。2.x系でALREADY_CONNECTEDが出るなら、サーバーかトランスポートを共有しているので、要求ごとに作る形への修正が必要です。413や400が返るなら、4MiBの本文上限か100件のバッチ上限に当たっているので、正当な要求ならmaxRequestBodySizeを上げます。全要求が401なら、expectedResourceだけを設定し、verifyAccessToken()がresourceを返していません。
Python SDKやFastMCPだけを使っている場合は対象ですか?
今回の7件はnpmで配布されるTypeScript版のパッケージの問題で、Python版のSDKは対象外です。ただしFastMCPには10月23日に2件の勧告が出ており、3系は3.4.10、4系は4.1.2が修正版になります。うちGHSA-vqqp-x5qm-5qp4は、クライアントの秘密を別の認可サーバーへ送りうる問題で、TypeScript版のCVE-2026-104850と同じ種類でした。FastMCPの版の追い方はFastMCP 4とはにまとめています。
リダイレクトの問題で秘密が漏れたかどうかは確かめられますか?
SDKの側に記録は残らないため、接続先のアクセスログで別オリジンへの307や308の応答が無いかを見るのが手がかりです。社外のサーバーでログを見られないなら、漏れた前提でAPIキーとclient_secretを入れ替え、トークンを失効させてください。MCP経由の権限の漏れ方はPlaywright MCPのセキュリティでも別の事例を扱っています。
関連記事
- MCP TypeScript SDK v2とは?パッケージ分割とステートレス化の移行要点:2.x系のパッケージ構成と1.x系からの移行手順を確認できます。
- MCP仕様2026-07-28版とは:ステートレス化の変更点と2025-11-25版からの移行手順:今回の修正の前提になった仕様の変更点です。
- CIMD(Client ID Metadata Documents)とは?MCPでDCRに代わるOAuthクライアント登録の仕組みと実装:MCPのOAuthクライアント登録を見直す際の基礎です。
- Playwright MCPのセキュリティ|危険性とCVE-2025-9611対策:MCPサーバー側の別の脆弱性の事例です。
- CVE(共通脆弱性識別子)とは?番号の読み方・CVSS/CWE/NVDとの違いと調べ方:GHSAとCVEの番号の対応を確かめるときに役立ちます。