Every CVE Search/ Get API key

CVE-2026-63128

RMCP: Unauthenticated permanent session-table leak in rmcp Streamable HTTP server transport leads to remote denial-of-service

7.5 HighFix available

RMCP is an official Rust SDK for the Model Context Protocol. Prior to 2.0.0, the rmcp crate's stateful Streamable HTTP server in crates/rmcp/src/transport/streamable_http_server/tower.rs allows an unauthenticated client to send a well-formed JSON-RPC POST that is not an initialization request, or an initialization request with a mismatched protocol header, causing StreamableHttpService::handle_post to call LocalSessionManager.create_session before validating the message. An early validation failure returns without removing the inserted LocalSessionHandle from LocalSessionManager.sessions, permanently retaining session and channel state for the server process lifetime. Repeated requests can grow the shared session table without bound, degrade legitimate-client latency through lock contention, exhaust memory, and terminate the server. This issue is fixed in version 2.0.0.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
None
Availability
High

Exploit likelihood

0.53%Unchanged since Sep 17, 2026
90%50%10%1%

What each source reports

CVE List Score used 7.5

RMCP: Unauthenticated permanent session-table leak in rmcp Streamable HTTP server transport leads to remote denial-of-service

RMCP is an official Rust SDK for the Model Context Protocol. Prior to 2.0.0, the rmcp crate's stateful Streamable HTTP server in crates/rmcp/src/transport/streamable_http_server/tower.rs allows an unauthenticated client to send a well-formed JSON-RPC POST that is not an initialization request, or an initialization request with a mismatched protocol header, causing StreamableHttpService::handle_post to call LocalSessionManager.create_session before validating the message. An early validation failure returns without removing the inserted LocalSessionHandle from LocalSessionManager.sessions, permanently retaining session and channel state for the server process lifetime. Repeated requests can grow the shared session table without bound, degrade legitimate-client latency through lock contention, exhaust memory, and terminate the server. This issue is fixed in version 2.0.0.

Record
CVE-2026-63128
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400, CWE-401, CWE-772
Updated
2026-11-02
EUVDEUVD-2026-80823 7.5

RMCP is an official Rust SDK for the Model Context Protocol. Prior to 2.0.0, the rmcp crate's stateful Streamable HTTP server in crates/rmcp/src/transport/streamable_http_server/tower.rs allows an unauthenticated client to send a well-formed JSON-RPC POST that is not an initialization request, or an initialization request with a mismatched protocol header, causing StreamableHttpService::handle_post to call LocalSessionManager.create_session before validating the message. An early validation failure returns without removing the inserted LocalSessionHandle from LocalSessionManager.sessions, permanently retaining session and channel state for the server process lifetime. Repeated requests can grow the shared session table without bound, degrade legitimate-client latency through lock contention, exhaust memory, and terminate the server. This issue is fixed in version 2.0.0.

Record
EUVD-2026-80823
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Updated
2026-11-02
GitHub AdvisoriesGHSA-9pj6-vhgr-3mwh 7.5

RMCP: Unauthenticated permanent session-table leak in rmcp Streamable HTTP server transport leads to remote denial-of-service

Summary

An unauthenticated remote attacker can leak one entry per HTTP request out of the in-memory session table of LocalSessionManager by sending a well-formed JSON-RPC POST that is not an InitializeRequest. The Streamable HTTP server's handle_post allocates the session before it validates the body, then early-returns on the validation failure without calling close_session. The LocalSessionHandle (and the tokio mpsc channel internals it holds) is never released for the remainder of the process's lifetime — turning a ~250-byte request into a permanent ~400–550-byte server-side allocation that scales linearly with request volume and eventually exhausts memory. In the verified reproduction below, a single Python client sustains over 2 000 leak requests per second; that translates to roughly 170 million leaked entries per day, equivalent to ≈75 GB of resident memory just from the session table.

Details

The bug lives in crates/rmcp/src/transport/streamable_http_server/tower.rs inside StreamableHttpService::handle_post. The relevant slice of 1.7.0 source (lines 1126–1170) is:

} else {
    let (session_id, transport) = self
        .session_manager
        .create_session()                                                  // (★)
        .await
        .map_err(internal_error_response("create session"))?;
    // ...capture init params if a SessionStore is configured...
    if let ClientJsonRpcMessage::Request(req) = &mut message {
        let ClientRequest::InitializeRequest(init_req) = &req.request else {
            return Err(unexpected_message_response("initialize request")); // (A)
        };
        validate_header_matches_init_body(                                 // (B)
            &part.headers,
            init_req.params.protocol_version.as_str(),
            Some(req.id.clone()),
        )?;
        req.request.extensions_mut().insert(part);
    } else {
        return Err(unexpected_message_response("initialize request"));     // (C)
    }
    let service = self
        .get_service()                                                     // (D)
        .map_err(internal_error_response("get service"))?;
    Self::spawn_session_worker(                                            // (★★)
        self.session_manager.clone(),
        session_id.clone(),
        service,
        transport,
        None,
    );
    // ...persist to external store, send response...
}

Two facts make this unsafe:

  1. (★) inserts a LocalSessionHandle into LocalSessionManager.sessions (a tokio::sync::RwLock<HashMap<SessionId, LocalSessionHandle>>) and spawns a LocalSessionWorker task.
  2. (★★) spawn_session_worker is the only code path in the entire transport (besides a client-initiated HTTP DELETE reaching handle_delete) that ever invokes self.session_manager.close_session(&session_id).

Therefore the four early-returns (A), (B), (C), and (D) all skip the cleanup. What happens concretely after such an early return:

  • The local transport: WorkerTransport<LocalSessionWorker> goes out of scope; its _drop_guard cancels the worker's CancellationToken.
  • The worker, which had been awaiting event_rx.recv(), exits within milliseconds via WorkerQuitReason::Cancelled. Its event_rx receiver is dropped.
  • LocalSessionHandle.event_tx (the Sender half of the same mpsc channel) is still alive because it is owned by the HashMap entry that nothing ever removes. The channel's Inner (sized to channel_capacity = 16 by default) remains pinned in memory.

Because the worker has already exited, the SessionConfig::keep_alive and init_timeout cleanup paths cannot run either — they only fire from inside a running worker. The leak is therefore permanent for the lifetime of the server process and grows unbounded with sustained traffic.

The bug is reachable with zero authentication, the default StreamableHttpServerConfig,…

Record
GHSA-9pj6-vhgr-3mwh
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400, CWE-401, CWE-772
Updated
2026-11-02
NVD 7.5

RMCP is an official Rust SDK for the Model Context Protocol. Prior to 2.0.0, the rmcp crate's stateful Streamable HTTP server in crates/rmcp/src/transport/streamable_http_server/tower.rs allows an unauthenticated client to send a well-formed JSON-RPC POST that is not an initialization request, or an initialization request with a mismatched protocol header, causing StreamableHttpService::handle_post to call LocalSessionManager.create_session before validating the message. An early validation failure returns without removing the inserted LocalSessionHandle from LocalSessionManager.sessions, permanently retaining session and channel state for the server process lifetime. Repeated requests can grow the shared session table without bound, degrade legitimate-client latency through lock contention, exhaust memory, and terminate the server. This issue is fixed in version 2.0.0.

Record
CVE-2026-63128
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400, CWE-401, CWE-772
Updated
2026-11-02
OSV 7.5

RMCP: Unauthenticated permanent session-table leak in rmcp Streamable HTTP server transport leads to remote denial-of-service

RMCP is an official Rust SDK for the Model Context Protocol. Prior to 2.0.0, the rmcp crate's stateful Streamable HTTP server in crates/rmcp/src/transport/streamable_http_server/tower.rs allows an unauthenticated client to send a well-formed JSON-RPC POST that is not an initialization request, or an initialization request with a mismatched protocol header, causing StreamableHttpService::handle_post to call LocalSessionManager.create_session before validating the message. An early validation failure returns without removing the inserted LocalSessionHandle from LocalSessionManager.sessions, permanently retaining session and channel state for the server process lifetime. Repeated requests can grow the shared session table without bound, degrade legitimate-client latency through lock contention, exhaust memory, and terminate the server. This issue is fixed in version 2.0.0.

Record
CVE-2026-63128
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400, CWE-401, CWE-772
Updated
2026-11-02
OSVGHSA-9pj6-vhgr-3mwh 7.5

RMCP: Unauthenticated permanent session-table leak in rmcp Streamable HTTP server transport leads to remote denial-of-service

Summary

An unauthenticated remote attacker can leak one entry per HTTP request out of the in-memory session table of LocalSessionManager by sending a well-formed JSON-RPC POST that is not an InitializeRequest. The Streamable HTTP server's handle_post allocates the session before it validates the body, then early-returns on the validation failure without calling close_session. The LocalSessionHandle (and the tokio mpsc channel internals it holds) is never released for the remainder of the process's lifetime — turning a ~250-byte request into a permanent ~400–550-byte server-side allocation that scales linearly with request volume and eventually exhausts memory. In the verified reproduction below, a single Python client sustains over 2 000 leak requests per second; that translates to roughly 170 million leaked entries per day, equivalent to ≈75 GB of resident memory just from the session table.

Details

The bug lives in crates/rmcp/src/transport/streamable_http_server/tower.rs inside StreamableHttpService::handle_post. The relevant slice of 1.7.0 source (lines 1126–1170) is:

} else {
    let (session_id, transport) = self
        .session_manager
        .create_session()                                                  // (★)
        .await
        .map_err(internal_error_response("create session"))?;
    // ...capture init params if a SessionStore is configured...
    if let ClientJsonRpcMessage::Request(req) = &mut message {
        let ClientRequest::InitializeRequest(init_req) = &req.request else {
            return Err(unexpected_message_response("initialize request")); // (A)
        };
        validate_header_matches_init_body(                                 // (B)
            &part.headers,
            init_req.params.protocol_version.as_str(),
            Some(req.id.clone()),
        )?;
        req.request.extensions_mut().insert(part);
    } else {
        return Err(unexpected_message_response("initialize request"));     // (C)
    }
    let service = self
        .get_service()                                                     // (D)
        .map_err(internal_error_response("get service"))?;
    Self::spawn_session_worker(                                            // (★★)
        self.session_manager.clone(),
        session_id.clone(),
        service,
        transport,
        None,
    );
    // ...persist to external store, send response...
}

Two facts make this unsafe:

  1. (★) inserts a LocalSessionHandle into LocalSessionManager.sessions (a tokio::sync::RwLock<HashMap<SessionId, LocalSessionHandle>>) and spawns a LocalSessionWorker task.
  2. (★★) spawn_session_worker is the only code path in the entire transport (besides a client-initiated HTTP DELETE reaching handle_delete) that ever invokes self.session_manager.close_session(&session_id).

Therefore the four early-returns (A), (B), (C), and (D) all skip the cleanup. What happens concretely after such an early return:

  • The local transport: WorkerTransport<LocalSessionWorker> goes out of scope; its _drop_guard cancels the worker's CancellationToken.
  • The worker, which had been awaiting event_rx.recv(), exits within milliseconds via WorkerQuitReason::Cancelled. Its event_rx receiver is dropped.
  • LocalSessionHandle.event_tx (the Sender half of the same mpsc channel) is still alive because it is owned by the HashMap entry that nothing ever removes. The channel's Inner (sized to channel_capacity = 16 by default) remains pinned in memory.

Because the worker has already exited, the SessionConfig::keep_alive and init_timeout cleanup paths cannot run either — they only fire from inside a running worker. The leak is therefore permanent for the lifetime of the server process and grows unbounded with sustained traffic.

The bug is reachable with zero authentication, the default StreamableHttpServerConfig,…

Record
GHSA-9pj6-vhgr-3mwh
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-400, CWE-401, CWE-772
Updated
2026-11-02
OSVRHSA-2026:80764 8.2

Red Hat Security Advisory: goose security update

Record
RHSA-2026:80764
CVSS 3.1
8.2 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N
Updated
2026-11-02
OSVRHSA-2026:80765 8.2

Red Hat Security Advisory: goose security update

Record
RHSA-2026:80765
CVSS 3.1
8.2 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N
Updated
2026-11-02
OSVopenSUSE-SU-2026:11849-1 No score

openai-codex-0.155.1-1.1 on GA media

These are all security issues fixed in the openai-codex-0.155.1-1.1 package on the GA media of openSUSE Tumbleweed.

Record
openSUSE-SU-2026:11849-1
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
rmcp
crates.io
before 2.0.0
2.0.0
goose
Red Hat:enterprise_linux:9::extensions
From an advisory covering 4 CVEs
before 0:1.45.0-1.el9_8
0:1.45.0-1.el9_8
goose-debuginfo
Red Hat:enterprise_linux:9::extensions
From an advisory covering 4 CVEs
before 0:1.45.0-1.el9_8
0:1.45.0-1.el9_8
goose-debugsource
Red Hat:enterprise_linux:9::extensions
From an advisory covering 4 CVEs
before 0:1.45.0-1.el9_8
0:1.45.0-1.el9_8
goose
Red Hat:enterprise_linux:10.2
From an advisory covering 4 CVEs
before 0:1.45.0-1.el10_2
0:1.45.0-1.el10_2
goose-debuginfo
Red Hat:enterprise_linux:10.2
From an advisory covering 4 CVEs
before 0:1.45.0-1.el10_2
0:1.45.0-1.el10_2
goose-debugsource
Red Hat:enterprise_linux:10.2
From an advisory covering 4 CVEs
before 0:1.45.0-1.el10_2
0:1.45.0-1.el10_2
openai-codex
openSUSE:Tumbleweed
From an advisory covering 3 CVEs
before 0.155.1-1.1
0.155.1-1.1

History

History
RecordedChangedSources
affected, facts
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-63128 is a high vulnerability (CVSS 7.5) in Modelcontextprotocol Rust-sdk, published September 16, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.53%, the 45th percentile. Fixed in rmcp 2.0.0.

References

Show 35 moreShow less
This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open