Buffer Everything, Expire Nothing: Three New CVEs in the Official MCP Python and Java SDKs
Three CVEs in the official Model Context Protocol SDKs reached NVD within the same hour today, 14 October 2026, all status Received, all unauthenticated remote denial of service over the HTTP transports that production MCP deployments actually expose. CVE-2026-109527 (Python SDK, CWE-770, CVSS 7.5 AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H) names unbounded request-body buffering in the Streamable HTTP session manager, the SSE message endpoint, and the OAuth authorization-server routes. CVE-2026-59951 (Python SDK, CWE-400, CVSS 4.0 6.9) names Streamable HTTP session state that is never reclaimed by default. CVE-2026-108395 (Java SDK, CWE-770, CVSS 7.5, same network vector) names unbounded body reads in the Servlet-based SSE, Streamable HTTP, and Stateless server transports. The headline is not the severity — availability-only, no confidentiality or integrity impact — it is the location: the reference implementations the whole ecosystem builds on had no resource limits on their network surface.
The second headline is the timeline, and it is arguably the more important one. The fixes for all three shipped in August and September; the CVE records arrived today. Anyone whose vulnerability management keys on CVE feeds has been blind to these for up to eight weeks while the advisories and fixed releases sat in public. Details below, because the gap differs per record.
One large request, two to three times its size in memory
CVE-2026-109527 affects mcp on PyPI before 1.29.1 and 2.0.0 through 2.0.1, fixed in 1.29.1 and 2.1.0 (there is no fixed 2.0.x release). Per the maintainer advisory GHSA-fmmv-w9g8-j3gc, an affected server read the whole body of every HTTP request into memory before checking its size, and one large request grew the process’s memory by two to three times the body size — so a client that could reach the server could exhaust its memory and take it offline, repeatedly. No credentials are needed against the OAuth endpoints (/token, /register, /revoke, /authorize), or against any server that does not require authentication, which is the default.
The fix arrived in two steps, and the staging matters. Versions 1.29.0 and 2.0.0 added a 4 MiB limit to the Streamable HTTP endpoint only; 1.29.1 and 2.1.0 extended it to the SSE transport’s message endpoint and the OAuth authorization-server routes. Every HTTP endpoint the SDK provides now reads the body through one shared limit (default 4 MiB, tunable via max_request_body_size) and answers 413 as soon as a request declares or streams more, before any parsing. One honest caveat survives in the advisory and is worth repeating: code that drives StreamableHTTPServerTransport directly, without the session manager, does not get the limit and should bound request bodies itself. The framework fixed the paths it owns; the escape hatch you wired by hand is still yours.
CVE-2026-108395 is the same bug in the Java SDK’s mcp-core artifact, and its details contain the nastiest line of the three records. All three Servlet-based transports buffered the entire incoming body with no maximum — and they did not check the Content-Length header, reading the body in a loop instead. A client using chunked transfer encoding could stream an arbitrarily large body past any declared-size check, driving heap usage without bound until OutOfMemoryError starved or crashed the process. A single request suffices. Affected lines are 0.18.x before 0.18.4, 1.x before 1.1.4, and 2.0.0; fixed in 0.18.4, 1.1.4, and 2.0.1, which enforce a maximum body size across all three transports and reject oversized requests before the body is fully buffered. The advisory notes two mitigating factors worth weighing honestly: the transports’ existing Origin/Host allow-list, and authentication checks implemented outside the SDK, both of which read headers and may reject a request before the body is read. “May” is doing work in that sentence — header-gated rejection only helps if you actually configured those gates.
Sessions that never die
CVE-2026-59951 is the subtler of the Python pair and the one with the longest affected window: versions 1.8.0 through 1.29.1 and 2.0.0 through 2.1.1, fixed in 1.30.0 and 2.2.0. Per GHSA-84m7-p3x7-pcfv, a Streamable HTTP server in stateful mode — the default for FastMCP, MCPServer, streamable_http_app(), and the session manager — never reclaimed session state. Sessions did not expire. A client DELETE ended the session but left its entry registered. A session whose first request was refused stayed registered with a running task. Each session kept its parsed initialize parameters, and the number of sessions was unlimited. A client that could reach the endpoint could grow server memory without bound using ordinary short requests; only a restart reclaimed it.
The fix bounds retention rather than eliminating it: idle sessions (default 30 minutes with nothing in flight) are closed and their IDs then answer 404; at most 10,000 sessions exist at once, with further opens answered 503; sessions are discarded on every end path — DELETE, expiry, or refused opening request. Both knobs are tunable and disableable, and the advisory is candid that a live session still holds its initialize parameters and that an invalid-parameters initialize still opens a session that expires like any other. The sentence we would underline for operators is this one: authentication limits who can open sessions, not how many a token holder can open. A valid credential plus a loop is still a complete exploit, which is exactly the shape that matters when MCP servers sit behind an agent framework holding long-lived tokens.
The pattern, the gap, and the Go-shaped hole
Step back and the three records describe one design assumption: the SDKs’ HTTP transports were written as though every client were trustworthy, so bodies could be buffered whole and sessions kept forever. That assumption was arguably fine when MCP servers were local stdio processes spawned by a desktop client. It is not fine now that the same SDKs serve Streamable HTTP to networks full of agents, browsers, and other people’s infrastructure — and the advisories say so in their own “am I affected” sections: yes, if clients you do not fully trust can reach the endpoint.
This is also the third week in a row the unbounded-body shape has appeared in an MCP SDK on this site. The mcp-go record from 12 October (CVE-2026-108859) is the identical bug — ServeHTTP calling io.ReadAll before validation — with one decisive difference: the Go SDK has no fixed version, while the Python and Java SDKs do. Three SDKs, one bug class, two fixed, one still open. If your fleet runs MCP servers in more than one language, that asymmetry is your patch-priority list. Our earlier 3 October SDK roundup covered a different set of advisories (redirects, task.session leakage, scanner gaps) — none of today’s three CVEs — which tells you something about the velocity here: the official SDKs are producing security advisories roughly as fast as anyone can write them up.
Finally, the disclosure gap deserves its own paragraph because it is actionable. The Java fix released 19 August with its advisory the same day; the Python body-limit fix released 24 August; the Python session-reclamation fix released 7 September with advisories on 30 September. The CVE records published today, 14 October. For seven to eight weeks, these were public advisories with public fixes and no CVE identifiers — invisible to every scanner, dashboard, and policy gate that keys on CVE feeds, which is most of them. The maintainers did the right thing (fix first, document publicly); the ecosystem’s detection layer still has a single point of failure in the CVE publication pipeline. If your program treats “no CVE” as “no vulnerability,” these three records are a clean counterexample with dates attached.
What to do
- Upgrade the SDKs. Python:
mcp>=1.29.1(1.x) or>=2.1.0(2.x) for the body limit — note there is no fixed 2.0.x, so 2.0.0 and 2.0.1 must move lines — and>=1.30.0/>=2.2.0for session reclamation. Java:mcp-core0.18.4, 1.1.4, or 2.0.1 matching your release line. If you only take one upgrade, take the session fix: it closes the slow-drip path that needs no large requests. - Check the Go SDK separately. If you also run mark3labs/mcp-go, CVE-2026-108859 had no fixed version as of our 12 October briefing — the mitigations there are a reverse proxy with a body cap, not an upgrade.
- Cap body size at the edge regardless. A reverse proxy or gateway enforcing a request-body limit, or ASGI middleware in front of the server, closes all three body-read paths at once — including the hand-driven
StreamableHTTPServerTransportpath the SDK fix does not cover. The advisories recommend exactly this for deployments that cannot upgrade yet. - Tune the session bounds to your host. The new defaults (30-minute idle expiry, 10,000 sessions) bound retention on a normal server; on a small host, lower
session_idle_timeout,max_sessions, andmax_request_body_sizetogether. Where you need no per-session state,stateless_http=Trueremoves the session surface entirely. - Stop gating detection on CVE publication. Subscribe to the SDK repositories’ security advisories (GHSA-fmmv-w9g8-j3gc, GHSA-84m7-p3x7-pcfv, GHSA-4x8c-5vv7-973f) directly. These three were public and fixed weeks before they became CVEs.
Verification note: all three CVE identifiers, NVD publication timestamps (14 October 2026, 17:18–18:17 UTC), CVSS vectors and scores, CWE assignments (CWE-770 twice, CWE-400 once), affected and fixed version ranges, vulnStatus values, and CNA attribution were read first-hand from the NVD 2.0 API. The mechanism descriptions, the 4 MiB limit and 413 behaviour, the two-step rollout of the Python body fix, the chunked-transfer-encoding detail, the session-retention specifics (DELETE and refused-open paths, retained initialize parameters), the fixed-version defaults (30-minute idle timeout, 10,000 sessions, 404/503 behaviours), the stdio/stateless exemptions, the direct-transport caveat, and the authentication-does-not-limit-count finding are as stated in the three maintainer advisories, fetched directly from GitHub on 14 October 2026. Release dates (Python 1.29.1/2.1.0 on 24 August, 1.30.0/2.2.0 on 7 September; Java 0.18.4/1.1.4/2.0.1 on 19 August) and advisory publication dates were read first-hand from the GitHub API. We installed no SDK, ran no server, sent no oversized or chunked request, and opened no sessions; everything above is read from source. Brave Search surfaced only CVE-mirror aggregators (Strix, Threat Radar, vuldb) and no analytical coverage.
Sources:
- NVD — CVE-2026-109527, Python SDK unbounded request-body buffering (published 14 October 2026, CVSS 3.1 7.5, CWE-770, status Received)
- NVD — CVE-2026-59951, Python SDK unreclaimed Streamable HTTP sessions (published 14 October 2026, CVSS 4.0 6.9, CWE-400, status Received)
- NVD — CVE-2026-108395, Java SDK unbounded request-body reads (published 14 October 2026, CVSS 3.1 7.5, CWE-770, status Received)
- GHSA-fmmv-w9g8-j3gc — HTTP server transports and OAuth endpoints read request bodies with no size limit (fixed 1.29.1 / 2.1.0)
- GHSA-84m7-p3x7-pcfv — Streamable HTTP sessions never reclaimed by default (fixed 1.30.0 / 2.2.0)
- GHSA-4x8c-5vv7-973f — Unbounded request-body reads in mcp-core HTTP server transports (fixed 0.18.4 / 1.1.4 / 2.0.1)