DEV Community

Cover image for HTTP/2 Bomb (CVE-2026-49975): the HPACK + flow-control DoS, and how to patch it
Kerry Kier
Kerry Kier Subscriber

Posted on • Originally published at blog.vertexops.org

HTTP/2 Bomb (CVE-2026-49975): the HPACK + flow-control DoS, and how to patch it

Two bugs that have each been public for a decade just got composed into one remote denial-of-service that knocks over five of the most widely deployed web servers in their default config. A single client on a home 100Mbps connection can pin roughly 32GB of RAM in about 20 seconds. No botnet, no credentials, one laptop.

The chain itself is not the interesting part. The interesting part is that an AI found it by reading the codebases and noticing two known-bad behaviors compose, and that the public patch is now enough for a model to rebuild the exploit. More on that below. First, what you need to know so you don't get knocked over.

Who's affected and what's patched

The vulnerable behavior is in the default HTTP/2 config of all five. There is no single CVE for the whole class -- Apache and Envoy each got their own.

Server Status Fix / mitigation
nginx Patched 1.29.8+ adds max_headers (default 1000)
Apache httpd Partial mod_http2 2.0.41 (standalone module / trunk); not in a stable 2.4.x as of disclosure
Envoy Patched CVE-2026-47774; fixed in 1.35.11, 1.36.7, 1.37.3, 1.38.1
Microsoft IIS No public fix I could find Disable HTTP/2 or front with a header-count cap
Cloudflare Pingora No public fix I could find Disable HTTP/2 or front with a header-count cap

Apache's variant is CVE-2026-49975. Envoy's is CVE-2026-47774. The remaining implementations may assign their own.

The chain

It's two primitives stacked.

HPACK indexed-reference amplification. HTTP/2 compresses headers with HPACK, which keeps a dynamic table of recently seen headers. You insert a header once, then reference it by a one-byte index on later requests, and the server materializes a full copy of that header in memory for each reference. One byte on the wire, one full header allocation on the server. Thousands of references in a single request turns a few KB of traffic into MB of RAM. Calif measured the multiplier at ~70:1 on nginx, ~4,000:1 on Apache and Envoy, and up to ~5,700:1 on Envoy. The trick that slips past the usual "max decoded header size" cap is the Cookie header, which RFC 9113 lets you split into one field per crumb, and which several servers weren't counting against their field-count limit.

The flow-control stall. Amplification alone is harmless if the memory frees when the request completes. The second primitive pins it: the client advertises a zero-byte flow-control window for the server's response, so the server can never finish replying and never reclaims the request's memory. Drip a periodic WINDOW_UPDATE to keep the connection from timing out and the allocation stays locked for as long as the server tolerates.

Compression bomb to inflate, slow-read hold to pin. That's the whole thing.

None of this is new, which is the actual story

Every piece has been public for years:

  • CVE-2016-6581 -- the original HPACK Bomb (Cory Benfield, 2016)
  • CVE-2016-8740 -- unbounded CONTINUATION frames, Apache (2016)
  • CVE-2016-1546 -- flow-control / worker-thread starvation, Apache (2016)
  • CVE-2025-53020 -- ~4,000x HPACK amplification, Apache (Gal Bar Nahum, 2025)

RFC 7541 ยง7.3 opens by warning that an attacker can try to exhaust an endpoint's memory. Five independent implementations read that and shipped the same class of bug anyway, which, as Calif notes, means the defect is in the spec, not in five separate teams.

What composed the two halves was OpenAI's Codex. It read across all five codebases, saw the techniques snap together, and built the combined attack. Researcher Quang Luong is presenting the method at a Stanford security conference this month. The combination is obvious once you see it, and that is exactly the point: nobody was looking at all five codebases at once with the patience to ask what happens when you run two known-bad behaviors at the same time. The composition lived in the seams between teams, and nobody owns the seams.

Why your patch cycle just changed

Here's the line from Calif's writeup that should bug you more than the DoS itself: the fix commits are out in the open, they map the attack directly, and any capable model can read the diff and reconstruct a working exploit. That's not hypothetical. It's how Calif confirmed IIS, Envoy, and Pingora were vulnerable in the first place. They fed the patch diffs to a model and let it generalize.

Responsible disclosure has always leaned on a gap between "patch published" and "exploit weaponized," filled by human effort: roll out the fix before attackers finish reversing it. When the diff alone is enough for a model to reconstruct the attack, that gap collapses toward zero. The grace period and the attacker's effort tax were the same thing, and it's evaporating. Plan your patch windows as if the PoC ships with the advisory, because functionally it now does.

Mitigations

nginx:

# 1.29.8+ adds max_headers (default 1000). Upgrade.
# Can't upgrade yet? Disable HTTP/2:
http2 off;
Enter fullscreen mode Exit fullscreen mode

Apache httpd:

# Fix is in mod_http2 2.0.41 (standalone / trunk),
# not yet in a stable 2.4.x as of disclosure.
# If you can't pull the module, disable HTTP/2:
Protocols http/1.1

# Note: lowering LimitRequestFieldSize only partially helps
# (it caps the merged cookie). LimitRequestFields does nothing
# here, because the duplicate cookie crumbs weren't counted against it.
Enter fullscreen mode Exit fullscreen mode

Envoy: upgrade to 1.35.11, 1.36.7, 1.37.3, or 1.38.1 (CVE-2026-47774). The fix makes uncompressed cookies count toward the header limits.

Microsoft IIS / Cloudflare Pingora: no public fix I could find as of this writing. Disable HTTP/2, or front the server with something that enforces a hard per-request header-count cap.

Everyone, regardless of vendor:

# Two limits, not one: cap decoded header SIZE and header COUNT
# (including cookie crumbs), and bound the lifetime of a stalled stream.
# If you can't do that yet, cap per-worker memory so a bombed worker
# gets OOM-killed and respawned instead of pushing the box into swap:
ulimit -v <kib>            # or cgroup memory.max, or container --memory
Enter fullscreen mode Exit fullscreen mode

A worker that dies clean and respawns is a far better failure mode than one holding the whole machine at 95% memory while every other request crawls.

Takeaway

The HTTP/2 Bomb gets patched everywhere in a few weeks. The condition that produced it doesn't. Our security debt isn't just the CVEs we know about, it's the backlog of obvious compositions nobody has run the numbers on, sitting in the seams between systems that each looked fine in isolation. The thing that used to protect us from that backlog was that checking it was tedious. That's gone. The tedium is free now, for defenders who choose to spend it and for everyone else regardless. Run the numbers on your own infrastructure before someone else does.


Timing note: this one is still moving. Envoy shipped its fix while the story was developing and others may follow. Everything here is accurate as of June 4, 2026. Check each vendor's advisory before you act.

Top comments (0)