Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-90678

CVE-2026-90678: HAProxy HTTP/3 RCE Vulnerability

CVE-2026-90678 is a remote code execution flaw in HAProxy affecting versions 3.3.0 through 3.4.4 that enables HTTP request smuggling through HTTP/3 frontends. This article covers technical details, affected versions, and mitigation.

Published:

CVE-2026-90678 Overview

CVE-2026-90678 is an HTTP Request Smuggling vulnerability in HAProxy affecting versions 3.3.0 through 3.4.4 and 3.5-dev1 through 3.5-dev5. The flaw exists in the HTTP/3 multiplexer, which credits the payload length declared in a DATA frame header to the stream's known-input-payload estimate before the payload is received. HAProxy then emits that declared length verbatim as the HTTP/1.1 chunk size on reused backend connections. A remote unauthenticated attacker can declare more payload than they deliver, desynchronizing the backend connection pool.

Critical Impact

An attacker can smuggle requests past frontend access controls such as path-based http-request deny rules and capture concurrent clients' request lines and Authorization headers as the smuggled request body.

Affected Products

  • HAProxy 3.3.0 through 3.3.x (built with QUIC support)
  • HAProxy 3.4.0 through 3.4.4
  • HAProxy 3.5-dev1 through 3.5-dev5

Discovery Timeline

  • 2026-09-13 - CVE-2026-90678 published to NVD
  • 2026-09-14 - Last updated in NVD database

Technical Details for CVE-2026-90678

Vulnerability Analysis

The vulnerability is a classic HTTP Request Smuggling [CWE-130] flaw arising from improper handling of length parameters during HTTP/3 to HTTP/1.1 protocol translation. Exploitation requires a specific configuration: HAProxy built with QUIC support, a QUIC bind listener for an HTTP/3 frontend, and backend traffic using HTTP/1.1 chunked transfer coding on reused connections.

When an HTTP/3 request arrives without a Content-Length header, the multiplexer parses the DATA frame header and immediately trusts the declared length. HAProxy translates the request to HTTP/1.1 and writes the declared length as the chunk size to the backend. If the client then ends the stream after sending fewer bytes than declared, HAProxy returns the connection to the idle pool while the backend still expects additional chunk bytes.

The next request that reuses that pooled connection is prepended with attacker-controlled bytes interpreted as continuation of the prior chunk. This allows an attacker to bypass frontend HTTP analysis, including path-based deny rules, and to consume concurrent clients' request lines and Authorization headers as the attacker's request body. Exploitation succeeds in a majority of trials during testing and can be retried freely.

Root Cause

The root cause resides in src/h3.c, where the HTTP/3 demultiplexer credited demux_frame_len to the stream endpoint's known-input-payload estimate at the moment the frame header was decoded, before validating that the payload was actually delivered. The mechanism was introduced in 3.3-dev10; releases 3.2.x and earlier are unaffected.

Attack Vector

A remote unauthenticated attacker sends an HTTP/3 request over QUIC with no Content-Length header and a DATA frame declaring a payload larger than what will be transmitted. The attacker terminates the stream early, causing HAProxy to write an oversized chunk size to the backend and return the desynchronized connection to the pool for reuse by other clients.

c
// Patch context from src/h3.c - BUG/MAJOR: h3: reject H3 truncated frames
	enum h3s_t type;
	enum h3s_st_req st_req; /* only used for request streams */
-	uint64_t demux_frame_len;
-	uint64_t demux_frame_type;
+	uint64_t demux_frame_len;  /* current parser frame remaining content to read */
+	uint64_t demux_frame_type; /* current parser frame type */

	unsigned long long body_len; /* known request body length from content-length header if present */
	unsigned long long data_len; /* total length of all parsed DATA */

Source: HAProxy commit 86a4ebc. The fix rejects H3 truncated frames so the declared DATA length is only credited once the payload is fully received.

Detection Methods for CVE-2026-90678

Indicators of Compromise

  • Backend HTTP/1.1 responses that do not correspond to any frontend request, or responses returned to the wrong client.
  • Log entries showing chunked responses where the announced chunk size exceeds the bytes actually written on the backend connection.
  • Unexpected requests reaching backends despite matching a http-request deny rule at the frontend.
  • Missing or truncated Authorization headers in downstream application logs during periods of HTTP/3 traffic.

Detection Strategies

  • Correlate HAProxy frontend access logs against backend application logs to identify request/response mismatches on reused connections.
  • Inspect HTTP/3 traffic for DATA frames whose declared length exceeds the QUIC stream bytes actually delivered before FIN.
  • Monitor for elevated rates of early stream terminations from unauthenticated HTTP/3 clients.

Monitoring Recommendations

  • Enable verbose HAProxy logging on QUIC listeners and forward events to a centralized SIEM for correlation.
  • Alert when backend chunk-size announcements diverge from bytes written on the same connection.
  • Track http-request deny bypass patterns, particularly requests reaching restricted paths that should have been blocked at the frontend.

How to Mitigate CVE-2026-90678

Immediate Actions Required

  • Upgrade HAProxy to a patched release that includes commit 86a4ebc761a278838e8cb06f3a292282ba704c65.
  • If patching is not immediate, disable the QUIC bind listener to remove the HTTP/3 frontend attack surface.
  • Audit backend applications for evidence of smuggled requests or leaked Authorization headers.

Patch Information

The fix is available in the HAProxy source tree. See the HAProxy commit log entry and the HAProxy 3.5 Changelog for the release containing the fix. The patch rejects truncated H3 frames so the declared DATA length is validated against bytes actually received before being emitted as an HTTP/1.1 chunk size.

Workarounds

  • Remove the quic4 or quic6 bind directive from HAProxy configuration to disable HTTP/3 frontends until the patch is applied.
  • Configure backends to use HTTP/2 or disable connection reuse on HTTP/1.1 backends to prevent desynchronized pooling.
  • Downgrade to HAProxy 3.2.x, which does not contain the vulnerable mechanism introduced in 3.3-dev10.
bash
# Disable HTTP/3 frontend by removing QUIC bind (workaround)
frontend fe_web
    bind :443 ssl crt /etc/haproxy/certs/site.pem
    # bind quic4@:443 ssl crt /etc/haproxy/certs/site.pem alpn h3
    default_backend be_app

# Or disable HTTP/1.1 backend connection reuse
backend be_app
    http-reuse never
    server app1 10.0.0.1:8080

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.