HTTP/2 Bomb (CVE-2026-49975): The Memory DoS an AI Found

An AI model read the source code of every major web server, noticed that two ten-year-old attacks could be bolted together, and wrote the exploit nobody had written. The result, CVE-2026-49975, the HTTP/2 Bomb, pushes an Envoy server from idle to roughly 32 GB of allocated memory in about ten seconds at an amplification ratio near 5,700:1. Disclosed publicly on 2 June 2026. Both halves of the trick had been sitting in the open since 2016. It just took something with infinite patience and no ego to notice they rhymed. The HTTP/2 Bomb is the rare CVE where the writeup is as interesting as the patch.

HTTP/2 Bomb CVE-2026-49975 memory exhaustion DoS attack

Pull up a chair. I’ve kept enough servers breathing through enough 3am pages to have firm opinions about HTTP/2, and this one’s a beauty, not because it’s clever in some galaxy-brained way, but because it’s boring. It’s two well-documented behaviours doing exactly what the spec says, multiplied together until your RAM evaporates. The CVSS score is 9.8. Critical. The kind of number that ruins a Tuesday.

And before you ask: yes, this is a different attack from HTTP/2 Rapid Reset. Rapid Reset (CVE-2023-44487) burned CPU by opening and cancelling streams. This one barely touches your CPU. It goes after memory, and it does it by exploiting the gap between two limits your server thought were the same limit. Let me show you.

The HTTP/2 Bomb in one idea: two limits, not one

Every defended HTTP/2 server caps the maximum decoded header size. Send a megabyte of headers and the server says “no thanks” and drops you. This cap exists precisely because of the original 2016 HPACK Bomb (CVE-2016-6581): stuff one enormous value into the compression table, reference it a thousand times, and a tiny request balloons into gigabytes once decompressed. We learned that lesson. We capped total decoded size. Problem solved, we thought.

Here’s the gap, and it’s the whole attack in one sentence: “maximum decoded header size” and “maximum header count” are two different limits, and most servers only enforced the first one. They counted the bytes. They didn’t count the fields. And it turns out the expensive part of a header isn’t the bytes, it’s the per-entry bookkeeping the server allocates around each field. Struct here, pointer there, a little metadata, an entry in a table. Do that ten thousand times with near-empty headers and you’ve spent almost no decoded bytes while forcing the server to allocate a mountain of accounting structures. The size cap never fires, because there’s almost no size. You walked straight under the bar.

Part one: the HPACK indexed-reference bomb (the cheap multiplier)

HTTP/2 compresses headers with HPACK, which keeps a dynamic table, a per-connection dictionary of headers you’ve already sent, so repeats cost one byte instead of the whole string. Lovely for efficiency. The attack seeds the table with one header, then emits thousands of one-byte indexed references to it. Each single wire byte expands into a full header field on the server side, and crucially, into the per-field bookkeeping that goes with it.

How expensive is each byte? Depends on the server’s internals, and the spread is wild. The discoverer’s measured numbers: each wire byte translates to somewhere between 70 and 4,000 bytes of server allocation. nginx, which is fairly lean, sits around 70:1. Apache, which rebuilds merged header strings repeatedly, hits roughly 4,000:1. Same protocol, same attack, two orders of magnitude difference purely from how each codebase chose to store a header. The spec was honest; the implementations each picked their own poison.

The Cookie crumb trick: how to dodge a header-count cap

“Fine,” says the server that did cap header count, smugly. “I limit you to 1,000 fields. Good luck.” And here’s where it gets gloriously petty. RFC 9113 §8.2.3 explicitly permits splitting the Cookie header into one field per crumb. That’s a real, deliberate feature, HTTP/2 lets a client send cookie: a=1, cookie: b=2, cookie: c=3 as separate fields for better compression, and the server is required by the standard to stitch them back together.

Most servers weren’t counting Cookie crumbs against their field limit, because spec-wise they’re “one logical header.” So the attacker pours thousands of empty cookie crumbs down the pipe. Each one is a field. Each field needs bookkeeping. And on Apache specifically, the server rebuilds the merged cookie string repeatedly as crumbs arrive, quadratic-ish string reconstruction over empty data, producing that ~4,000:1 amplification with cookies that contain literally nothing. You’re not even sending data. You’re sending the idea of data, and the server does all the work.

Part two: the window stall, pinning the memory so it never frees

A bomb that detonates and clears up isn’t much of a bomb. You’d allocate, respond, free, and recover. So the second half of the attack makes sure the server can never let go of what it allocated. This is a Slowloris-style hold dressed up in HTTP/2 flow control.

HTTP/2 has per-stream flow control: the receiver advertises a window saying “I can accept this many bytes of your response right now.” The attacker advertises a zero-byte window. The server, obedient, prepares its response, holds it in memory, and waits to send, because the client has said it can’t receive a single byte yet. The response, and every allocation behind it, is now pinned. Then, to stop the server’s idle timeout from giving up and freeing everything, the attacker drips one-byte WINDOW_UPDATE frames, each one resetting the send timeout. Just enough life support to look alive, never enough to drain the buffer. Every allocation stays nailed in place. Multiply across thousands of streams across thousands of connections and you are out of memory in seconds.

HTTP/2 Bomb CVE-2026-49975 attack chain: HPACK indexed-reference bomb plus Cookie crumb amplification plus zero-window flow-control stall pin memory until the server runs out of RAM
The full chain: cheap indexed references and empty cookie crumbs inflate per-field bookkeeping, then a zero-byte flow-control window with drip-fed WINDOW_UPDATE frames pins every allocation so it never frees.

The numbers, because they’re genuinely frightening

The discoverer published demo figures, and they’re the kind of thing you read twice. These are single-attacker results, not botnets:

ServerAmplificationDemo result
Envoy 1.37.2~5,700:1~32 GB in ~10 s
Apache httpd 2.4.67~4,000:1~32 GB in ~18 s
nginx 1.29.7~70:1~32 GB in ~45 s
Microsoft IIS~68:1~64 GB in ~45 s

nginx’s relatively modest 70:1 is the upside of a lean codebase, it still falls over, just more slowly. Envoy’s 5,700:1 is what happens when rich internal data structures meet an attack that bills you per structure. Note there’s no botnet column. One machine. One attacker. Tens of gigabytes. That asymmetry is the entire point of a DoS, and this is one of the cleanest ratios ever published against mainstream software.

How to defend it, patch first, then defence in depth

Good news, mostly: the responsible-disclosure process worked, and the fix is conceptually simple once you name the bug. The bug was “we counted bytes, not fields.” The fix is “count fields too.” Here’s the layered defence.

nginx, upgrade to 1.29.8+ and meet max_headers

nginx was told in April 2026 and shipped a fix the next day, a turnaround that deserves a quiet round of applause. Version 1.29.8 adds a new max_headers directive that caps the header field count independently of size, defaulting to 1000. That default is sane for almost everyone; lower it if your app genuinely never sends a thousand headers (it doesn’t).

# nginx 1.29.8+
http2 on;
max_headers 1000;   # new directive: caps header FIELD count, default 1000

Can’t upgrade today? Turn HTTP/2 off until you can:

http2 off;

Apache httpd, mod_http2 v2.0.41

Disclosed to Apache on 27 May 2026; Stefan Eissing committed a fix the same day (these maintainers are not messing around). The fix lives in mod_http2 v2.0.41, available from the standalone mod_http2 releases and in httpd trunk, but at disclosure it was not yet in a 2.4.x release. The patch makes Cookie crumbs count against LimitRequestFields. Until you can deploy it, lowering LimitRequestFieldSize is a partial mitigation, or kill HTTP/2 outright:

# Apache: disable HTTP/2 until mod_http2 2.0.41 is deployed
Protocols http/1.1

IIS, Envoy, Cloudflare Pingora, no patch yet

At disclosure, Microsoft IIS, Envoy, and Cloudflare Pingora had no patch available. If you run these on a public HTTP/2 endpoint, your options are: disable HTTP/2 where you can, or front the server with something that enforces a hard cap on header-field count per request. A reverse proxy or WAF that rejects requests with absurd field counts turns the bomb into a dud before it reaches the vulnerable allocator. This is, incidentally, exactly the architecture we run, a hardened nginx/Angie front edge that can be told “no request needs 9,000 cookie crumbs, drop it.”

The general principle

If you write protocol code: treat “maximum decoded size” and “maximum field count” as separate, independent limits. They are not proxies for each other. Bytes are cheap; bookkeeping is not. Anywhere a client can make you allocate a per-item structure, count the items and cap them, even if each item is empty, especially if each item is empty, because empty is exactly what an attacker will send.

The lesson, because there’s always a lesson

The two ingredients, HPACK reference amplification and flow-control stalling, were public for a decade. Anyone could have read them. The reason nobody combined them isn’t that it was hard; it’s that it lived in the seam between two specialisms, and humans are bad at the seams. We file HPACK under “compression,” flow control under “transport,” and never think to multiply them. An AI model with no such filing system read both codebases end to end and saw one attack where we saw two unrelated footnotes.

That’s the real story here, and it’s coming for every protocol you run. The next decade of vulnerabilities won’t all be novel bugs. A lot of them will be old, documented, individually-harmless behaviours that nobody bothered to compose, dragged into the light by something that reads faster than you and forgets nothing. The defence is the same as it’s always been, count what costs you, cap what a stranger can make you do, and assume the seams between your subsystems are exactly where the next bomb is hiding. Go check your nginx version. I’ll wait.

Frequently asked questions

Is CVE-2026-49975 the same as HTTP/2 Rapid Reset?

No. Rapid Reset (CVE-2023-44487) is a CPU-exhaustion attack that opens and instantly cancels streams. The HTTP/2 Bomb (CVE-2026-49975) is a memory-exhaustion attack: it inflates per-header-field bookkeeping with cheap HPACK indexed references and empty Cookie crumbs, then pins those allocations in memory with a zero-byte flow-control window. Different resource, different mechanism, both abuse HTTP/2’s design rather than a coding bug.

Am I vulnerable, and how do I check?

If you serve HTTP/2 on nginx before 1.29.8, Apache httpd without mod_http2 2.0.41, or any version of Microsoft IIS, Envoy, or Cloudflare Pingora at disclosure, you are exposed in the default configuration. Check your nginx version with `nginx -v` and your Apache mod_http2 version. The vulnerability is in the default HTTP/2 config, so you do not need any special setup to be affected.

What is the fastest way to mitigate if I cannot patch?

Disable HTTP/2. On nginx use `http2 off;`, on Apache set `Protocols http/1.1`. Alternatively, front your server with a reverse proxy or WAF that enforces a hard cap on the number of header fields per request, that rejects the bomb before it reaches the vulnerable allocator. Disabling HTTP/2 costs you multiplexing performance but stops the attack dead.

Why do empty cookies cause so much damage?

RFC 9113 §8.2.3 lets a client split the Cookie header into one field per crumb, and many servers did not count those crumbs against their header-field limit. Each crumb still forces a per-field allocation, and Apache rebuilds the merged cookie string repeatedly as crumbs arrive, producing roughly 4,000:1 amplification even when every cookie is empty. The damage comes from per-entry bookkeeping, not from the data, so empty crumbs are the most efficient payload.

How was the HTTP/2 Bomb discovered?

An AI model (Codex) analysed the source code of major web servers and recognised that two long-public techniques, the 2016 HPACK indexed-reference bomb and HTTP/2 flow-control stalling, could be composed into a single new attack. Both halves had been documented for about a decade; the contribution was reading the codebases, seeing that they combine, and building the combined exploit.

How bad is it really?

CVSS 9.8 (Critical). A single attacker, no botnet, drove demo servers to roughly 32 GB of memory in 10 to 45 seconds, with amplification ratios from about 70:1 on nginx up to about 5,700:1 on Envoy. Because it exhausts memory rather than CPU, it can take a server fully offline (OOM-killed) extremely quickly, which is why patching or disabling HTTP/2 is urgent.

Related reading