Sep 17, 2026·6 min read·62 visits
The stateful HTTP server in the rmcp crate allocates session resources before validating request headers and bodies. If validation fails, the server exits early without reclaiming the allocated memory, leading to an unbounded memory leak and eventual server crash.
CVE-2026-63128 is a high-severity uncontrolled resource consumption vulnerability in the Model Context Protocol (MCP) official Rust SDK (the rmcp crate) prior to version 2.0.0. An unauthenticated attacker can exploit this vulnerability by sending malformed or mismatching handshake requests to the stateful Streamable HTTP server, causing persistent memory allocation without cleanup. This results in an unbounded memory leak and lock contention that ultimately leads to complete denial of service.
The Model Context Protocol (MCP) official Rust SDK (the rmcp crate) contains an uncontrolled resource consumption vulnerability within its stateful Streamable HTTP server transport layer. This component, located in crates/rmcp/src/transport/streamable_http_server/tower.rs, exposes an endpoint for stateful communication over HTTP. The server relies on a central, stateful session table to track and process active bidirectional messaging contexts between clients and the server.
Under normal execution, clients must establish a stateful session by sending a valid JSON-RPC initialization request matching the expected version headers. The vulnerability manifests when an unauthenticated client transmits a message that fails validation before a session worker is fully initialized. This action causes the server to permanently retain state structures without ever invoking a cleanup path.
The vulnerability is classified under CWE-400 (Uncontrolled Resource Consumption), CWE-401 (Missing Release of Memory after Effective Lifetime), and CWE-772 (Missing Release of Resource after Effective Lifetime). Because this component is exposed to untrusted network traffic, unauthenticated attackers can remotely invoke the vulnerable path, inducing a persistent memory leak and resulting in a denial of service.
The root cause of CVE-2026-63128 lies in an asymmetric resource allocation-to-cleanup lifecycle in StreamableHttpService::handle_post. When an HTTP POST request is received, the server attempts to process the message context. However, it allocates and registers a new session state before validating the client's request message structure and matching protocol headers.
Specifically, the function invokes LocalSessionManager.create_session() as one of its first operations. This call instantiates a LocalSessionHandle inside the shared, thread-safe sessions table (backed by an RwLock<HashMap<SessionId, LocalSessionHandle>>) and allocates active Tokio multi-producer single-consumer (MPSC) channels. At this point, memory is allocated and registered globally.
Following allocation, the handler evaluates the request body to verify if it is an InitializeRequest and validates that the MCP-Protocol-Version HTTP header matches the protocol version declared in the payload. If either validation check fails, the handler aborts execution early and returns an error response (such as HTTP 400 or 422). Because the corresponding cleanup worker task (spawn_session_worker) has not been spawned, the registered LocalSessionHandle is never purged from the active session map, leaving it permanently orphaned.
The vulnerable implementation of handle_post executes the allocation sequence prior to validating the message variant or headers. The following representation demonstrates how early error handling pathways bypass the cleanup registration.
// Vulnerable execution sequence in tower.rs
let (session_id, transport) = self
.session_manager
.create_session()
.await
.map_err(internal_error_response("create session"))?;
if let ClientJsonRpcMessage::Request(req) = &mut message {
let ClientRequest::InitializeRequest(init_req) = &req.request else {
// Error response is returned immediately; create_session state is leaked
return Err(unexpected_message_response("initialize request"));
};
// Headers are checked after create_session has succeeded
validate_header_matches_init_body(
&part.headers,
init_req.params.protocol_version.as_str(),
Some(req.id.clone()),
)?;
} else {
return Err(unexpected_message_response("initialize request"));
}The patch introduced in commit dfa7fd6f9309deab60bea230b041be9a3fcda846 remediates this vulnerability by validating both the incoming payload and headers before allocating any system resources. If the request fails header matching or contains an unexpected message type, the handler returns an error response without ever invoking create_session(). This prevents the creation of dangling handles in the sessions collection.
// Patched execution sequence in tower.rs
let stored_init_params = match &mut message {
ClientJsonRpcMessage::Request(req) => {
let ClientRequest::InitializeRequest(init_req) = &req.request else {
return Err(unexpected_message_response("initialize request"));
};
validate_header_matches_init_body(
&part.headers,
init_req.params.protocol_version.as_str(),
Some(req.id.clone()),
)?;
let stored_init_params = self
.config
.session_store
.as_ref()
.map(|_| init_req.params.clone());
req.request.extensions_mut().insert(part);
stored_init_params
}
_ => {
return Err(unexpected_message_response("initialize request"));
}
};
let service = self
.get_service()
.map_err(internal_error_response("get service"))?;
// Session allocation is deferred until validation successfully passes
let (session_id, transport) = self
.session_manager
.create_session()
.await
.map_err(internal_error_response("create session"))?;Exploitation of this vulnerability requires network access to the stateful Streamable HTTP server endpoint. No authentication or elevated credentials are required to initiate the vulnerable execution path. The attacker constructs a well-formed JSON-RPC POST payload that uses a valid method schema but does not perform the mandatory initial handshake.
An attacker can transmit a message such as a request calling a non-initialization method (e.g., tools/list or resources/list) to the stateful server endpoint. Alternatively, an attacker can transmit an InitializeRequest with mismatched values between the MCP-Protocol-Version HTTP header and the internal protocol version defined in the JSON payload body.
Upon receiving the request, the server allocates stateful tracking objects and writes them to the memory table. Since the payload fails structural validation, the connection is closed and an error response is returned, leaving the allocated session dangling in memory. By executing this routine in a high-frequency loop, an attacker can continuously grow the server's session table, causing memory exhaustion and critical lock contention.
The primary operational impact of CVE-2026-63128 is a complete denial of service. Because each validation failure leaks an active session handle, memory consumption grows linearly based on the volume of unauthenticated requests transmitted by the attacker. Eventually, the operating system's Out-Of-Memory (OOM) killer will terminate the server process.
Furthermore, the shared session table is governed by a read-write lock (RwLock). Each insertion of a leaked session handle requires a write lock on the table, which blocks read operations. The continuous insertion of orphaned sessions creates severe lock contention, resulting in high latency or execution timeouts for legitimate active client connections long before the process memory is fully exhausted.
The CVSS v3.1 score is calculated as 7.5, reflecting network-based, low-complexity attack paths requiring no active authentication or user interaction. There is no impact on confidentiality or integrity, as the vulnerability does not permit unauthorized data access or arbitrary code execution.
Remediation of CVE-2026-63128 requires upgrading the rmcp crate to version 2.0.0 or higher. This release integrates the validation-first logic that prevents allocating memory for malformed or mismatched handshake requests.
For systems where immediate upgrades are not feasible, network-level mitigations can reduce the risk of exploitation. Administrators can deploy reverse proxies or Web Application Firewalls (WAF) to drop POST requests targeting the /mcp endpoints that lack the correct initialization structures or matching headers. This ensures that only pre-validated requests reach the stateful HTTP server.
Rate-limiting should also be enforced on HTTP endpoints. Restricting the frequency of POST requests per source IP address mitigates high-volume attacks that attempt to rapidly expand the memory footprint or cause lock contention on the session manager's shared structures.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
rmcp modelcontextprotocol | < 2.0.0 | 2.0.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-400 / CWE-401 / CWE-772 |
| Attack Vector | Network |
| CVSS v3.1 Score | 7.5 (High) |
| Exploit Status | None |
| CISA KEV Listed | No |
| Mitigated Version | 2.0.0 |
The software does not control the allocation and maintenance of a limited resource, enabling an actor to trigger a denial of service.
CVE-2026-118777 is a prototype pollution vulnerability (CWE-1321) in the Forge JavaScript cryptography and networking library (distributed on npm as node-forge) prior to version 1.4.1. The flaw resides in the forge.http client subsystem, where incoming HTTP cookie names and paths parsed from Set-Cookie response headers are stored directly into standard JavaScript objects without key validation or property isolation. By returning crafted Set-Cookie headers containing keys such as __proto__ or constructor, a malicious HTTP server can inject arbitrary properties into Object.prototype, attach attributes to the global Object constructor, or delete built-in prototype methods to cause an application-wide denial of service.
CVE-2026-118775 (GHSA-4642-5mcj-2rqw) is an integer overflow and validation flaw in the ASN.1 serialization module of Forge (node-forge) prior to version 1.4.1. The asn1.oidToDer() function fails to validate the range of the first two arcs of an Object Identifier (OID) and truncates the packed initial subidentifier to a single 8-bit integer. Applications that perform policy checks on untrusted OID strings before encoding them into Distinguished Encoding Rules (DER) format can be tricked into emitting DER bytes that correspond to a completely different, restricted OID.
CVE-2026-119194 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting versions 0.3.3 through 0.6.4. The flaw resides in the schemaless decoding routine ConstructedPayloadDecoderBase._decodeComponentsSchemaless used across BER, CER, and DER codecs. By sending an ASN.1 container populated with child components whose tag identifiers are separated by multiples of CPython's integer hash modulus (sys.hash_info.modulus), an unauthenticated attacker can force worst-case hash collisions in an unbounded Python set, degrading decoding performance from O(N) to O(N^2) and causing a Denial of Service (DoS).
CVE-2026-119195 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting all versions prior to 0.6.5. When decoding constructed strings or indefinite-length ANY types across BER, CER, and certain DER code paths, the payload decoders repeatedly concatenate incoming fragments onto an immutable bytes object using the += operator. Because Python bytes objects cannot be resized in-place, each fragment iteration allocates a new buffer and copies all previously accumulated bytes, resulting in quadratic O(N^2) time and memory copy complexity. An unauthenticated remote attacker can supply a highly fragmented ASN.1 stream to exhaust CPU cycles and stall application worker threads.
An algorithmic complexity vulnerability (CWE-407) in pyasn1 versions prior to 0.6.5 allows unauthenticated attackers to cause a Denial of Service (DoS) via crafted ASN.1 payloads. The flaw resides in the binary-encoded ASN.1 REAL mantissa deserialization routine within RealPayloadDecoder.valueDecoder. By performing iterative byte-string slicing and repeated bitwise shifts on a growing arbitrary-precision integer, the decoder exhibits quadratic time and memory allocation complexity relative to the mantissa length. Supplying a BER-, CER-, or DER-encoded payload with a large REAL mantissa causes excessive CPU consumption and blocks application worker processes.
A vulnerability classified under CWE-407 (Inefficient Algorithmic Complexity) exists in the pyasn1 library prior to version 0.6.5. When parsing constructed ASN.1 BIT STRING payloads under BER, CER, or schema-driven DER encoding rules, the BitStringPayloadDecoder repeatedly shifts and copies the entire accumulated bit value for each incoming fragment. Processing inputs with a large number of small constructed fragments induces quadratic CPU consumption, allowing unauthenticated remote attackers to cause a denial of service via resource exhaustion during the initial decoding phase.