Apr 2, 2026·7 min read·4 visits
mcp-handler < 1.1.0 relies on a vulnerable Model Context Protocol SDK that misroutes JSON-RPC responses and server-initiated messages between concurrent clients when transport instances are incorrectly reused.
A race condition in the underlying Model Context Protocol (MCP) TypeScript SDK causes a tool response leak across concurrent client sessions. The `mcp-handler` package prior to version 1.1.0 exposes applications to this cross-client data leak due to improper lifecycle management of transport and protocol instances in stateless environments.
The mcp-handler package serves as a Vercel adapter for the Model Context Protocol (MCP), enabling seamless integration of MCP functionality within serverless environments. Advisory GHSA-W2FM-25VW-VH7F addresses a critical cross-client data leak resulting from a race condition in the underlying @modelcontextprotocol/sdk package. Applications utilizing mcp-handler versions prior to 1.1.0 inherently inherit this vulnerability.
The core issue stems from concurrent execution using shared resources with improper synchronization (CWE-362). In stateless deployments such as serverless functions, application state is often preserved across sequential invocations or shared concurrently during high load. If an MCP server or transport instance is instantiated globally or outside the immediate request-handling scope, concurrent incoming connections mutate the same underlying protocol objects.
This shared state mutation directly causes a session bleed. The vulnerability manifests primarily as the exposure of sensitive information to unauthorized actors (CWE-200). Subsequent sections detail the specific mechanics of the JSON-RPC message identifier collision and transport reference overwrite that facilitate this exposure.
The vulnerability originates from the architectural management of server and transport instances within the MCP TypeScript SDK (versions 1.10.0 through 1.25.3). Specifically, the flaw is triggered when a single StreamableHTTPServerTransport instance processes multiple concurrent client requests. The underlying mechanism involves a JSON-RPC message ID collision combined with destructive internal mapping behavior.
The MCP client SDKs generate JSON-RPC message identifiers using an incrementing numeric counter that initializes at zero for each new session. When concurrent clients connect to a stateless server instance sharing a transport, multiple clients frequently transmit requests containing identical message IDs. The StreamableHTTPServerTransport class maintains an internal dictionary mapping requestId directly to the corresponding network stream.
When a second client transmits a request possessing an identifier already registered in the internal dictionary by a first client, the transport implementation unconditionally overwrites the existing entry. The dictionary state now associates the shared message ID exclusively with the second client's stream. This behavior compromises the integrity of the request-response routing logic within the protocol layer.
An independent mechanism exacerbates the flaw when a single McpServer instance connects to multiple transports sequentially or concurrently. The internal Protocol class maintains a singular this._transport reference. Invoking .connect(transport) for an incoming client session actively overwrites this reference. Consequently, server-initiated payloads, such as sampling requests or progress notifications, are blindly dispatched to whichever transport was most recently connected, completely ignoring the session origin of the active process.
The architectural failure occurs when developer implementations attempt to optimize performance by hoisting object instantiation outside the request context. This pattern is common in serverless environments to minimize cold-start latency. The vulnerable logic sequence is modeled below.
The remediation implemented in @modelcontextprotocol/sdk@1.26.0 relies on strict lifecycle enforcement and state validation. The patch introduces explicit runtime invariants to prevent the silent overwriting of transport mappings and protocol references. The fix ensures the implementation explicitly rejects anomalous state mutations.
The Protocol.connect() method was modified to throw a deliberate exception if the protocol object is already connected to an active transport. This guard prevents the this._transport variable from being silently overwritten during concurrent invocations. Similarly, the StreamableHTTPServerTransport.handleRequest() function now enforces a strict single-use policy in stateless operational modes.
Furthermore, the patch enhances resource cleanup routines associated with aborted requests. Abort controllers corresponding to in-flight requests are correctly finalized upon the closure of the transport layer. This architectural adjustment ensures that dangling asynchronous operations cannot resolve and attempt to write to disconnected or reassigned transport streams.
Exploitation of this vulnerability requires the attacker to possess network access and sufficient authentication to interact with the target MCP server. The vulnerability is assigned a Low privileges required (PR:L) metric, indicating the attacker only needs standard access to the application utilizing the MCP framework. No specialized access to the underlying infrastructure or administrative consoles is necessary.
The attack vector relies on highly synchronized concurrent HTTP requests. The attacker initializes a session and transmits an MCP JSON-RPC request while continuously monitoring the temporal execution of a target victim's workflow. The objective is to transmit a request that generates an identical JSON-RPC message ID (typically 0 or 1) at precisely the moment the victim's request is in-flight on the server.
Successful execution of this race condition results in the target server overwriting the internal stream dictionary mapping. Upon completion of the victim's requested operation, the server retrieves the overwritten stream reference and transmits the victim's tool response directly through the attacker's HTTP connection. The attacker passively collects the leaked JSON payload.
As a consequence of the misrouting, the original victim client receives no response from the server. The victim's internal protocol handlers will eventually encounter a timeout condition, causing the local application process to hang or terminate with an error. Active exploitation therefore produces a distinct localized denial-of-service indicator alongside the data exfiltration event.
The primary security impact of this vulnerability is the violation of data confidentiality. MCP tool responses frequently contain highly sensitive internal information, including database query results, proprietary intellectual property retrieved from local file systems, or raw outputs from Large Language Models. Unauthorized access to this data allows an attacker to bypass logical application boundaries and extract protected context.
The integrity impact is assessed as Low, primarily stemming from the mishandling of server-initiated sampling or elicitation requests. If the server requests workflow input via the createMessage or sendRequest functions, and this request is misrouted to the attacker, the attacker can supply arbitrary input. This attacker-controlled input is subsequently processed by the server under the context of the victim's active session.
The vulnerability carries a CVSS v3.1 base score of 7.1, categorized as High severity. The vector string CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N correctly identifies the remote, low-complexity nature of the exploit and highlights the significant confidentiality risk. The lack of direct availability impact (A:N) reflects the fact that the underlying service infrastructure remains operational, despite individual victim requests timing out.
The specific execution environment dictates the exact exploitability. Deployments utilizing stateless serverless compute platforms (such as AWS Lambda or Vercel edge functions) are highly susceptible if developers employ global variable caching for McpServer or StreamableHTTPServerTransport instances. Implementations utilizing persistent Node.js servers (e.g., Express) with strict per-connection object instantiation remain structurally immune to this specific race condition.
The immediate requirement for all affected organizations is to update the target dependencies. Developers must upgrade the mcp-handler package to version 1.1.0 or later. Concurrently, the peer dependency @modelcontextprotocol/sdk must be upgraded to version 1.26.0 or greater. This ensures the integration of the runtime guards within the core protocol logic.
In scenarios where immediate package upgrades are administratively prohibited, developers must manually verify and refactor their implementation architecture. The application code must guarantee the instantiation of unique, isolated server and transport objects strictly within the boundary of the incoming HTTP request handler. Global or module-level variable assignment for these components must be strictly eliminated.
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
app.post('/api/mcp', async (req, res) => {
const server = new McpServer({ name: "secure-server", version: "1.0.0" });
const transport = new StreamableHTTPServerTransport();
await server.connect(transport);
await transport.handleRequest(req, res);
});Security operations personnel should configure application performance monitoring to detect anomalous request timeouts associated with MCP endpoints. An unexpected spike in client-side timeout events, correlated with high concurrent request volumes, functions as a reliable behavioral indicator of either an active exploitation attempt or an inherently vulnerable architectural configuration under load.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
mcp-handler Vercel | < 1.1.0 | 1.1.0 |
@modelcontextprotocol/sdk Model Context Protocol | >= 1.10.0, < 1.26.0 | 1.26.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-362 (Race Condition) |
| Attack Vector | Network |
| CVSS v3.1 | 7.1 (High) |
| Confidentiality Impact | High |
| Integrity Impact | Low |
| Availability Impact | None |
| Exploit Status | Unauthenticated access via concurrent requests |
Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')