無限制請求正文如何在各主要 MCP SDK 中形成拒絕服務漏洞類別
The first of its kind: how one unbounded request body became a denial-of-service class across every major MCP SDK
CVE-2026-39313 揭示,MCP HTTP 傳輸中未限制大小的請求正文可在無需驗證下耗盡伺服器記憶體,造成拒絕服務。其後至少另外九個 MCP 專案發現相同問題,修補方式多為設定預設 4 MiB 請求正文上限。
文章梳理無限制請求正文漏洞如何擴散至多個 MCP SDK,並指出核心 SDK 的漏洞通報未進入常用掃描資料庫,令直接核對版本成為必要防護環節。
The one-line version
In April 2026 I reported CVE-2026-39313, a denial-of-service flaw in an MCP server framework. It was the first CVE of its kind: an unbounded HTTP request body, CWE-770, that lets a single unauthenticated request exhaust a Model Context Protocol server's memory and take it offline.
Over the next six months the identical flaw was found and patched in at least nine more MCP projects, including the official Python, Java, Go, Ruby, PHP and TypeScript SDKs. A third-party analysis in July called it "a new vulnerability category." By October two of those CVEs sat in the SDKs that the whole ecosystem is built on, together serving close to half a billion downloads a month.
This is the story of that class: how far it spread, who patched and who is still exposed, and why the two worst ones are effectively invisible to the scanners most teams rely on.
Every claim below links to a primary source.
What the bug actually is
MCP servers speak over an HTTP transport: Streamable HTTP, Server-Sent Events, and OAuth routes. To handle a request, the server reads the request body into memory before it does anything else.
The flaw is simple and brutal. The read loop has no size limit. It keeps appending chunks to a buffer until the client stops sending or the process dies. There is no authentication in front of it, because the body is read before any auth check runs. So an attacker who can reach the endpoint sends one large POST, or a slow endless stream, and the server allocates memory until it is killed by the OOM reaper. One request, one dead server, no credentials required.
This is CWE-770, allocation of resources without limits. It is not exotic. That is exactly why it turned up everywhere.
CVE-2026-39313: the first one
The first public advisory of this class was in mcp-framework, a popular TypeScript framework for building MCP servers.
In versions 0.2.21 and below, the readRequestBody() function in the HTTP transport concatenated body chunks into a string with no cap. The framework even had a maxMessageSize configuration value, but readRequestBody() never referenced it. The limit existed on paper and was never enforced in code. A single large POST to /mcp crashed the server.
I reported it, it was fixed in 0.2.22, and the advisory published on 16 April 2026.
- Advisory (GitHub, GHSA-353c-v8x9-v7c3): https://github.com/QuantGeekDev/mcp-framework/security/advisories/GHSA-353c-v8x9-v7c3
- CVSS 4.0 8.7 (High), CWE-770
At the time it looked like one framework's mistake. It was not.
It was not a bug. It was a pattern.
Here is the timeline of the same unbounded-body denial-of-service turning up across the MCP ecosystem, as advisories and patches landed through 2026:
- 16 April — mcp-framework, CVE-2026-39313 (the first).
-
April to June — Google's MCP Toolbox for Databases had the identical
io.ReadAllwith no limit, reported four days after my advisory and fixed in June. No advisory, no CVE. - July — the official Go SDK added a request-body cap, shipped as OOM protection in its release notes, with no advisory and no CVE.
- 30 July — the Ruby SDK, CVE-2026-67432. A 512 MB POST grew a worker from 44 MB to 1.66 GB. Fixed with a 4 MiB default cap.
- 19 August — the PHP SDK, CVE-2026-53965, the client-side version: an unbounded SSE buffer. The Java SDK shipped a matching client-side SSE fix the same day.
- 16 September — rmcp, the Rust SDK, CVE-2026-63128.
- 11 October — mcp-go, CVE-2026-108859.
- 14 October — the official Python SDK, CVE-2026-109527, and the official Java SDK, CVE-2026-108395. Both credited to me among the reporters.
- 20 and 27 October — the official TypeScript SDK, CVE-2026-111768 and a follow-up advisory.
Nine-plus independent projects. The same root cause. The same fix every single time: a default body-size cap, almost always 4 MiB.
In July an independent write-up looked at this and called CVE-2026-39313 the first documented denial-of-service against the MCP HTTP transport and "a new vulnerability category." That is the right framing. This was not a run of unrelated bugs. It was one design gap in how MCP transports read input, replicated across every language the protocol ships in.
The two that carry the protocol
Most of the class lived in frameworks and bindings. Two of them did not. They were in the reference SDKs that nearly every MCP deployment imports.
CVE-2026-109527, the official Python SDK (mcp). In versions before 1.29.1, and in the 2.0 pre-releases through 2.0.1, the Streamable HTTP session manager, the SSE message endpoint, and the OAuth authorization-server routes all buffered complete request bodies with no maximum size. An unauthenticated remote client could send a large declared or streamed body that consumed several times its own size in process memory, and repeat it until the server died.
- Advisory (GHSA-fmmv-w9g8-j3gc): https://github.com/modelcontextprotocol/python-sdk/security/advisories/GHSA-fmmv-w9g8-j3gc
- Fixed in 1.29.1. CVSS 7.5 (High), CWE-770.
- The
mcppackage serves over 235 million downloads a month on PyPI.
CVE-2026-108395, the official Java SDK. Unbounded request-body reads in the mcp-core HTTP server transports, same class, same impact.
- Advisory (GHSA-4x8c-5vv7-973f): https://github.com/modelcontextprotocol/java-sdk/security/advisories/GHSA-4x8c-5vv7-973f
- CVSS 7.5 (High), CWE-770.
For scale: the official TypeScript SDK pulls around 257 million downloads a month, the Python SDK 235 million. When the flaw sits in the SDK rather than a single server, every server built on that SDK inherits it the moment it exposes an HTTP transport.
Who patched, and who is still exposed
Red Hat rated CVE-2026-109527 Important, assessed 44 of its products, and issued three errata:
- RHSA-2026:92510 (OpenShift AI 3.4), RHSA-2026:92666 and RHSA-2026:92667 (Satellite 6.19 and 6.18).
- Of the 44 products assessed, 35 are affected, 6 not affected, 3 marked will-not-fix.
- https://access.redhat.com/security/cve/CVE-2026-109527
Debian tracks the same CVE against python-mcp at severity grave, and at the time of writing the package in unstable is still unfixed.
Downstream products started bumping their pins through October: OpenMetadata merged its upgrades, Red Hat's Open Data Hub opened fix PRs, and several hundred automated "bump mcp" pull requests have landed across GitHub since the advisories went live.
So the serious operators with security teams are moving. The question is everyone else.
The specification still does not require this
For all the patching, the root cause has never been closed at the design level. As of early November 2026 the MCP security best-practices document still contains no guidance on request-body size limits. Every SDK solved it independently, with its own default, because the specification never told them to. That is why the same fix had to be rediscovered six, seven, eight times over.
The MCP server security guidance that does exist, including the National Security Agency and CISA information sheet on MCP, discusses resource-exhaustion denial of service as a general risk but points implementers at no concrete control for this. The one place that could stop the whole class at the design level still does not mention it.
The blind spot: most scanners cannot see the worst two
This is current as of 3 November 2026, and it may change the day the databases catch up. Check it yourself.
CVE-2026-39313, the npm one, has a full global GitHub advisory. It is in OSV, it is in npm audit, and a scan of a vulnerable project flags it.
The two SDK CVEs do not behave the same way. CVE-2026-109527 and CVE-2026-108395 exist only as repository-level advisories on the Python and Java SDK projects. They were never promoted into the global GitHub Advisory Database. The downstream effect is a chain of blindness:
- They are absent from the global GitHub advisory mirror, so GitHub Dependabot does not alert on them.
- They are absent from OSV, so
osv-scannerand everything built on OSV misses them. Querying a vulnerablemcpversion returns the other 2026 CVEs but not this one. - They have no record in the PyPA advisory database, so
pip-auditfinds nothing. - NVD lists both as "Awaiting Analysis" with no version data, so even NVD-driven scanners have no range to match on.
The practical result: a server running a vulnerable mcp package can be scanned by pip-audit, osv-scanner, Dependabot, or a popular MCP-specific scanner that wraps pip-audit, and come back clean for the denial-of-service flaw. The patch shipped, the advisory was written, and the machine-readable plumbing that is supposed to warn people never carried it.
The enterprise distribution trackers, Red Hat, Debian and SUSE, do carry it, because they ingest from their own CNA and NVD feeds. Red Hat has even published a machine-readable VEX file for it. But the developer-facing supply-chain tools that most teams actually run do not. If you depend on pip-audit or Dependabot to tell you about this, right now they will not.
What an attacker gets, and who is at risk
You are exposed if you run an MCP server that:
- exposes an HTTP-based transport (Streamable HTTP or SSE), as opposed to stdio only, and
- is reachable by any client you do not fully trust, which includes the public internet, a shared internal network, or a browser-reachable origin, and
- runs a vulnerable version of the framework or SDK below.
The attack needs no authentication, no credentials, and no user interaction. One oversized or endless request crashes the process. Repeat it and the service stays down. It is trivially scriptable. There is no data theft here, the impact is pure availability, but for an agent backend that other systems depend on, taking it offline on demand is the whole game.
Stdio-only servers and deployments already sitting behind a reverse proxy with its own request-body limit are not exposed in the same way. That proxy limit is also your fastest mitigation while you patch.
The fix
Upgrade. The fixed versions:
- mcp-framework (npm): 0.2.22 or later.
-
MCP Python SDK (
mcpon PyPI): 1.29.1 or later. The fix addsmax_request_body_sizewith aDEFAULT_MAX_REQUEST_BODY_SIZEof 4 MiB in the transport security layer. -
MCP Java SDK: the patched
mcp-corerelease. -
MCP Go SDK: v1.7.0 or later, which enforces
DefaultMaxRequestBodyBytesof 4 MiB. -
Ruby SDK (
mcpgem): 0.23.0 or later. -
PHP SDK, Rust
rmcp, mcp-go, TypeScript SDK: upgrade to the latest; all shipped the same body-size cap through the autumn.
If you cannot upgrade immediately, put a reverse proxy in front with a client body limit (for example nginx client_max_body_size), and make sure your HTTP transport is not reachable from untrusted networks. Where your SDK exposes a configurable limit, set it explicitly rather than trusting the default, especially if you legitimately handle large payloads.
How to find it in your estate
- Inventory every MCP server you run and whether it exposes an HTTP transport or stdio only.
- For Python, do not trust
pip-auditalone for this one today. Check the installedmcpversion directly: anything below 1.29.1 is vulnerable. - For npm,
npm auditwill catch mcp-framework below 0.2.22. - For Java and Go, check the SDK version against the fixed releases above, because the advisories are not yet in the global databases your SCA tooling reads.
- Grep your own HTTP handlers for the pattern itself: a body read with no length cap,
io.ReadAll(r.Body)in Go,request.body.readwith no bound in Ruby, astring +=chunk loop in Node, before any size check. If you wrote a custom transport, you may have reproduced the class yourself.
The lesson
The MCP ecosystem grew faster than its security guidance. A single gap in how transports read input became a denial-of-service class that reached every major SDK in the protocol, and the one control that prevents it is still not written into the specification.
The fixes exist now. The specification guidance still does not. And for the two CVEs in the core SDKs, the automated warning system that the rest of us depend on is, as of today, silent. If you run MCP in production, do not wait for a scanner to tell you. Check the versions yourself.
References
- CVE-2026-39313, mcp-framework: https://github.com/QuantGeekDev/mcp-framework/security/advisories/GHSA-353c-v8x9-v7c3
- CVE-2026-109527, MCP Python SDK: https://github.com/modelcontextprotocol/python-sdk/security/advisories/GHSA-fmmv-w9g8-j3gc
- CVE-2026-108395, MCP Java SDK: https://github.com/modelcontextprotocol/java-sdk/security/advisories/GHSA-4x8c-5vv7-973f
- Red Hat, CVE-2026-109527: https://access.redhat.com/security/cve/CVE-2026-109527
- Debian tracker (grave), python-mcp: https://bugs.debian.org/1151047
- OWASP AISVS, MCP transport payload-size control citing CVE-2026-39313: https://github.com/OWASP/AISVS/blob/main/1.0/research/chapters/C10-MCP-Security/C10-04-Schema-Message-Validation.md
Raza Sharif, CyberSecAI Ltd. Reported CVE-2026-39313 and is credited on CVE-2026-109527 and CVE-2026-108395. All vulnerabilities were handled through coordinated disclosure and are fixed in the versions listed above. Contact: contact@agentsign.dev.
來源:DEV Community · dev.to