A remote, unauthenticated HTTP/3 client can desynchronize HAProxy’s reused backend connections, slip requests past a frontend deny rule, and swallow other users’ Authorization headers — and the newest release on both maintained branches sits inside the affected range.
What happened
NVD published CVE-2026-90678 at 4:17 a.m. UTC on Sunday, September 13, 2026, with MITRE as the assigning source and a CVSS v3.1 base score of 7.5. The record describes an HTTP request smuggling condition in HAProxy’s HTTP/3 multiplexer and classifies it as CWE-130, improper handling of length parameter inconsistency. The vector is CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:H/A:L — network-reachable, no privileges, no user interaction, high attack complexity, scope changed.
The preconditions are narrow, and the record states them precisely. HAProxy must be built with QUIC support and configured with a QUIC bind listener — an HTTP/3 frontend. The affected traffic must then reach a backend, in the record’s words, “over HTTP/1.1 using chunked transfer coding on a reused connection.” Both halves are required. An installation that terminates HTTP/2 over TCP, or that does not reuse backend connections, is not in scope.
Where those conditions hold, the record describes the mechanism in more detail than a CVE description usually carries. When an HTTP/3 request arrives with no Content-Length header, “the HTTP/3 multiplexer credits the length declared in a DATA frame header to the stream endpoint’s known-input-payload estimate at the moment the frame header is decoded, before the payload has been received, and that declared length is emitted verbatim as the HTTP/1.1 chunk size.” A client that declares more payload than it delivers and then ends the stream leaves HAProxy announcing a chunk larger than the bytes it actually writes — and then returning that connection to the idle pool in a desynchronized state.
Two consequences follow, and the record names both. An attacker can “place a request past a frontend rule such as a path-based http-request deny, so that the smuggled request is never seen by HAProxy’s HTTP analysis.” The request reaches the backend without passing the access control that was meant to stop it. Separately, other clients sharing that reused backend connection can have “their request lines and Authorization headers” consumed as the attacker’s request body and lost — a credential disclosure and a dropped request in the same event.
The record is unusually candid about reliability: “Exploitation is not deterministic; it depends on a race with backend connection pooling, succeeding in a majority of but not all trials during testing, and can be retried freely.”
On versions, the record says the mechanism “was introduced in 3.3-dev10” and that “releases 3.2.x and earlier are unaffected.” NVD’s configuration data lists 3.3.0 through 3.3.14, 3.4.0 through 3.4.4, and 3.5-dev1 through 3.5-dev5 as affected, with 3.5-dev6 and later unaffected.
The fix is a commit, and the branches it must be backported to have not shipped it
Those two ranges are the story. HAProxy’s own source directories list 3.3.14, posted August 27, 2026, as the highest release on the 3.3 branch, and 3.4.4, also posted August 27, 2026, as the highest release on 3.4. Both are the top of their branch, and both are named as affected. There is no 3.3.15 and no 3.4.5. The 3.4 changelog’s newest section opens “2026/08/27 : 3.4.4” and lists no HTTP/3 frame-handling fix among its entries.
What does carry the fix is a commit. The record’s only references are two copies of the same change — 86a4ebc761a278838e8cb06f3a292282ba704c65, on git.haproxy.org and on GitHub — and the 3.5 branch changelog. The commit is titled “BUG/MAJOR: h3: reject H3 truncated frames,” touches a single file, src/h3.c, adding 30 lines and removing four, and is credited to the project’s QUIC maintainer. It reports the issue as found by Rajat Raghav, cites RFC 9114 Section 7.1 — “HTTP/3 frames contain a length header. If a frame is truncated, the connection must be immediately closed with H3_FRAME_ERROR” — and describes the new checks as “crucial to prevent potential request content smuggling.”
It also says, in the project’s standard form: “This must be backported to all stable releases.” That sentence is an instruction to the maintainers, not a statement that the work is done — and as of this writing no published tarball carries it.
Why it matters
There is no vendor security advisory attached to this record. HAProxy handles serious bugs the way many C-language infrastructure projects do — in the commit log, with a severity prefix that maintainers read and scanners do not. “BUG/MAJOR” is the project’s own top-tier classification, and it appeared in the tree before any CVE existed. For a shop tracking HAProxy by release announcements or by a package feed, the first signal that anything was wrong arrived this morning, in a CVE record whose affected range includes the version they are almost certainly running.
That gap between commit-level disclosure and release-level remediation is the recurring shape here. This site has now covered several records in two weeks whose affected range terminates at something other than a version a person can install — a git commit hash in the case of AVideo’s seventeen records, a Red Hat container image in the case of crun, an unfixed abandoned package in the case of passport-saml-encrypted. HAProxy’s variant is the cleanest of the set: the range is stated in ordinary version numbers, the numbers are real releases, and the newest one on each maintained branch is inside the range. A scanner will report this correctly and an administrator will have nowhere to go.
The impact deserves separating into its two halves, because they land on different people. The access-control bypass is the one a security team will care about: a path-based http-request deny in the frontend is a boundary a great many deployments rely on to keep /admin, /metrics, or an internal API off the public edge, and a smuggled request is never analyzed by the rule engine at all. The credential half is the one users will feel. An Authorization header consumed as somebody else’s request body is a bearer token or a basic-auth credential handed to an attacker who did not have to break anything cryptographic to get it, plus a legitimate request that simply vanishes.
The narrowness of the preconditions is real and worth holding onto. QUIC support is a build-time option, and an HTTP/3 bind listener is an explicit configuration choice — plenty of HAProxy fleets have neither. But the second condition is close to a default in the deployments that do: HTTP/3 at the edge, plain HTTP/1.1 to the origin, with connection reuse left on because turning it off costs latency and sockets. That is the standard shape of a QUIC-terminating edge proxy, not an exotic one. The population at risk is smaller than “everyone running HAProxy” and larger than the attack-complexity rating suggests.
What to do
No published HAProxy release fixes this. The following are derived from the record’s own stated preconditions, not from a vendor advisory, because there is not one.
- Establish whether you are in scope at all. Run
haproxy -vvand look for QUIC support in the build options. Then check your configuration for aquic4@orquic6@bind listener. No QUIC build or no QUIC listener means this does not apply to you. - If you are in scope, break one of the two conditions. Removing the QUIC bind listener and serving HTTP/2 over TCP at the edge removes the entry condition outright. Alternatively,
http-reuse neveron the affected backends removes the reused-connection condition — at a genuine cost in latency and backend sockets, which is why it is the second choice rather than the first. - Do not treat a path-based
http-request denyas a boundary while you are exposed. If something behind the proxy is protected only by a frontend deny rule, protect it at the backend as well for the duration. - If you build from source, commit
86a4ebc761a278838e8cb06f3a292282ba704c65againstsrc/h3.cis a 30-line change and applies to the stable branches by the maintainer’s own note. - 3.2.x and earlier are not affected, per the record. For a fleet that has not yet moved off 3.2, that is a reason to wait rather than hurry.
- Watch for 3.3.15 and 3.4.5. When they appear, the changelog entry to look for is the one naming truncated H3 frames.
Sourcing note
Checked: the NVD record for CVE-2026-90678, read directly from the NVD API, for the description, score, vector, CWE, references, and affected version configuration. HAProxy’s own source download directories for the 3.3 and 3.4 branches, for the highest released version on each and its posting date. The 3.4 branch changelog, for its newest section heading and contents. The commit referenced by the record, read through its GitHub mirror, for the title, severity prefix, file changed, line counts, backport instruction, reporter credit, and RFC citation.
Could not reach: git.haproxy.org, which returned an anti-automation interstitial rather than the commit page; the GitHub mirror of the identical commit was used instead. No vendor security advisory page for this CVE was found, and the record references none.
Unresolved: whether a backport to 3.3 and 3.4 is imminent or whether the maintainers intend to fold it into the normal release cadence — the commit’s backport note sets no date. The 3.5 changelog published on haproxy.org did not resolve, on the reading available here, which of its development snapshots first carried the change; the version boundary of 3.5-dev6 in this story comes from NVD’s configuration data, not from the changelog. Exploitation reliability is described only by the record’s own testing, with no independent reproduction available. There is no evidence of exploitation in the wild, and none is claimed.
