CVE-2026-69202 Overview
CVE-2026-69202 is a resource exhaustion vulnerability [CWE-400] in http4s, a Scala interface for HTTP services. The flaw affects the Ember server and client when configured with HTTP/2 support (withHttp2). Ember replenishes its HTTP/2 flow-control window based on bytes received from the network rather than bytes consumed by the application. Each stream stores inbound DATA frames in an unbounded channel. A hostile peer can transmit a request or response body faster than a slow application drains it, causing payloads to accumulate on the heap. The issue is fixed in versions 0.23.35 and 1.0.0-M47.
Critical Impact
Remote unauthenticated attackers can exhaust JVM heap memory on ember-server or ember-client instances configured for HTTP/2, resulting in denial of service.
Affected Products
- http4s ember-server with withHttp2 prior to 0.23.35
- http4s ember-client with withHttp2 prior to 0.23.35
- http4s 1.0.0-M1 through releases prior to 1.0.0-M47
Discovery Timeline
- 2026-09-15 - CVE-2026-69202 published to the National Vulnerability Database
- 2026-09-16 - Last updated in NVD database
Technical Details for CVE-2026-69202
Vulnerability Analysis
The vulnerability resides in Ember's HTTP/2 implementation, specifically in H2Connection.scala within the ember-core module. HTTP/2 uses per-stream flow-control windows to signal how much data a receiver is willing to accept. A correct implementation ties WINDOW_UPDATE frames to application consumption so that a slow consumer produces backpressure across the network. Ember instead issued flow-control credit based on network reception, decoupling on-wire acknowledgement from downstream processing. Inbound DATA frames were pushed into an fs2.Channel.unbounded, so bytes queued indefinitely when the application read slowly or not at all. A remote peer holding many streams open, or a single high-throughput stream, can push arbitrary volumes of body data into heap-resident channels. The result is out-of-memory failure on both ember-server and ember-client deployments.
Root Cause
The root cause is an unbounded producer-consumer queue in the HTTP/2 stream body path combined with flow-control accounting that ignores application consumption. Because credit is returned before bytes are consumed, HTTP/2 backpressure semantics are violated. This maps to [CWE-400] Uncontrolled Resource Consumption.
Attack Vector
An unauthenticated network attacker who can establish an HTTP/2 connection to an ember-server, or who can serve responses to an ember-client, sends body data faster than the application reads it. No authentication or user interaction is required. The attacker holds streams open and continues writing DATA frames until the JVM heap is exhausted.
// Patch excerpt: ember-core/shared/src/main/scala/org/http4s/ember/core/h2/H2Connection.scala
request <- Deferred[F, Either[Throwable, org.http4s.Request[fs2.Pure]]]
response <- Deferred[F, Either[Throwable, org.http4s.Response[fs2.Pure]]]
trailers <- Deferred[F, Either[Throwable, org.http4s.Headers]]
- body <- Channel.unbounded[F, Either[Throwable, ByteVector]]
+ body <- Channel.bounded[F, Either[Throwable, ByteVector]](128)
refState <- Ref.of[F, H2Stream.State[F]](
H2Stream.State(
H2Stream.StreamState.Idle,
Source: http4s commit 22d2335. The patch replaces the unbounded body channel with a bounded channel of capacity 128, so producer writes block once the consumer falls behind and application consumption drives HTTP/2 flow-control credit.
Detection Methods for CVE-2026-69202
Indicators of Compromise
- Sustained JVM heap growth on services running ember-server or ember-client with HTTP/2 enabled
- OutOfMemoryError in application logs correlated with long-lived HTTP/2 connections
- Heap dumps showing large retained sets under org.http4s.ember.core.h2.H2Stream body channels holding ByteVector instances
- HTTP/2 peers sending large DATA payloads while the local application reads slowly or is stalled
Detection Strategies
- Inventory JVM services and identify http4s versions prior to 0.23.35 or 1.0.0-M47 that call .withHttp2 on EmberServerBuilder or EmberClientBuilder.
- Enable JVM heap and GC telemetry on affected services and alert on sustained old-generation growth without corresponding request throughput.
- Instrument HTTP/2 stream counts and per-connection inbound byte rates to identify peers that push data faster than the application consumes it.
Monitoring Recommendations
- Collect and centralize JVM metrics (heap.used, gc.pause, threads.count) from all http4s services.
- Log HTTP/2 stream lifecycle events, including duration and inbound byte totals, and forward them to a SIEM or data lake for anomaly analysis.
- Alert on connections that maintain many concurrent streams with growing inbound queue depth against a single tenant.
How to Mitigate CVE-2026-69202
Immediate Actions Required
- Upgrade http4s to 0.23.35 on the 0.23.x branch, or to 1.0.0-M47 on the 1.0.0 milestone branch.
- Audit all deployments that call EmberServerBuilder.withHttp2 or EmberClientBuilder.withHttp2 and prioritize their remediation.
- Restart affected JVM processes after upgrading to release any queued body data still held in memory.
Patch Information
Fixes are published in the http4s v0.23.35 release and the http4s v1.0.0-M47 release. See the GHSA-6m4x-pp6q-5jmm advisory for full disclosure details and the upstream commit for the code change. The patch bounds the per-stream H2Connection body channel so application consumption applies backpressure to the HTTP/2 flow-control window.
Workarounds
- Disable HTTP/2 on ember-server and ember-client by removing .withHttp2 from builder configuration until the upgrade is complete.
- Terminate HTTP/2 at an upstream reverse proxy (for example, nginx or Envoy) and speak HTTP/1.1 to the ember service.
- Enforce per-connection request size and timeout limits at the network edge to constrain the memory a single peer can pin.
# sbt: pin http4s to a patched version
# build.sbt
libraryDependencies ++= Seq(
"org.http4s" %% "http4s-ember-server" % "0.23.35",
"org.http4s" %% "http4s-ember-client" % "0.23.35"
)
# Temporary workaround: build ember without HTTP/2
# EmberServerBuilder
# .default[IO]
# .withHost(host"0.0.0.0")
# .withPort(port"8080")
# // .withHttp2 <-- remove until upgraded
# .build
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.