{"slug": "the-first-of-its-kind-how-one-unbounded-request-body-became-a-denial-of-service", "title": "The first of its kind: how one unbounded request body became a denial-of-service class across every major MCP SDK", "summary": "A security researcher reported CVE-2026-39313, an unbounded HTTP request body denial-of-service flaw (CWE-770) in the mcp-framework TypeScript framework, which was patched in version 0.2.22 in April 2026. Over the following six months the same root cause was found and patched in at least nine more MCP projects, including the official Python, Java, Go, Ruby, PHP and TypeScript SDKs, with the Python SDK (CVE-2026-109527) and Java SDK (CVE-2026-108395) among the most consequential given their combined download volume. The researcher notes the two worst cases are effectively invisible to common scanners.", "body_md": "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.\n\nOver 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.\n\nThis 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.\n\nEvery claim below links to a primary source.\n\nMCP 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.\n\nThe 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.\n\nThis is CWE-770, allocation of resources without limits. It is not exotic. That is exactly why it turned up everywhere.\n\nThe first public advisory of this class was in **mcp-framework**, a popular TypeScript framework for building MCP servers.\n\nIn 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.\n\nI reported it, it was fixed in 0.2.22, and the advisory published on 16 April 2026.\n\nAt the time it looked like one framework's mistake. It was not.\n\nHere is the timeline of the same unbounded-body denial-of-service turning up across the MCP ecosystem, as advisories and patches landed through 2026:\n\n`io.ReadAll` with no limit, reported four days after my advisory and fixed in June. No advisory, no CVE.\nNine-plus independent projects. The same root cause. The same fix every single time: a default body-size cap, almost always 4 MiB.\n\nIn 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.\n\nMost 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.\n\n**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.\n\n`mcp` package serves over **CVE-2026-108395, the official Java SDK.** Unbounded request-body reads in the `mcp-core` HTTP server transports, same class, same impact.\n\nFor 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.\n\n**Red Hat** rated CVE-2026-109527 **Important**, assessed 44 of its products, and issued three errata:\n\n**Debian** tracks the same CVE against `python-mcp` at severity **grave**, and at the time of writing the package in unstable is still unfixed.\n\nDownstream 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.\n\nSo the serious operators with security teams are moving. The question is everyone else.\n\nFor 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.\n\nThe 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.\n\nThis is current as of 3 November 2026, and it may change the day the databases catch up. Check it yourself.\n\nCVE-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.\n\nThe 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:\n\n`osv-scanner` and everything built on OSV misses them. Querying a vulnerable `pip-audit` finds nothing.\nThe 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.\n\nThe 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.\n\nYou are exposed if you run an MCP server that:\n\nThe 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.\n\nStdio-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.\n\nUpgrade. The fixed versions:\n\n`max_request_body_size` with a `DEFAULT_MAX_REQUEST_BODY_SIZE` of 4 MiB in the transport security layer.`mcp-core` release.`DefaultMaxRequestBodyBytes` of 4 MiB.`rmcp`, mcp-go, TypeScript SDK\nIf 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.\n\n`npm audit` will catch mcp-framework below 0.2.22.`io.ReadAll(r.Body)` in Go, `request.body.read` with no bound in Ruby, a `string +=` chunk loop in Node, before any size check. If you wrote a custom transport, you may have reproduced the class yourself.\nThe 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.\n\nThe 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.\n\n*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](mailto:contact@agentsign.dev).*", "url": "https://wpnews.pro/news/the-first-of-its-kind-how-one-unbounded-request-body-became-a-denial-of-service", "canonical_source": "https://dev.to/razashariff/the-first-of-its-kind-how-one-unbounded-request-body-became-a-denial-of-service-class-across-every-38", "published_at": "2026-11-03 12:16:21+00:00", "updated_at": "2026-11-03 12:26:53.165633+00:00", "lang": "en", "topics": ["ai-agents", "agent-protocols", "ai-tools", "developer-tools", "ai-safety"], "entities": ["Model Context Protocol", "mcp-framework", "Python SDK", "Java SDK", "TypeScript SDK", "CVE-2026-39313", "CVE-2026-109527", "CVE-2026-108395"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/the-first-of-its-kind-how-one-unbounded-request-body-became-a-denial-of-service", "markdown": "https://wpnews.pro/news/the-first-of-its-kind-how-one-unbounded-request-body-became-a-denial-of-service.md", "text": "https://wpnews.pro/news/the-first-of-its-kind-how-one-unbounded-request-body-became-a-denial-of-service.txt", "jsonld": "https://wpnews.pro/news/the-first-of-its-kind-how-one-unbounded-request-body-became-a-denial-of-service.jsonld"}}