Skip to content
Security & Trust

FoxIO finds 7 of 10 tested HTTP/3 stacks let small requests swell memory

FoxIO found that most HTTP/3 stacks it tested cap the compressed request, not what it unpacks into.

W
WebPulse Newsroom
AI-assisted · 4 min read
Share on X LinkedIn
FoxIO finds 7 of 10 tested HTTP/3 stacks let small requests swell memory
In brief
  • FoxIO found that seven of ten HTTP/3 implementations it tested can be made to hold far more memory than a client sends. One connection can be enough.
  • Affected stacks cap the compressed request instead of the unpacked headers. The Hacker News reports service disruption only, with no sign of data theft and no public attacks.
  • Teams should find which HTTP/3 library they run, upgrade to fixed releases, and ask who enforces the header limit.

A zip file the size of a postcard can unpack into a drive full of data. Security teams have known that trick for years. FoxIO, a security firm, now reports that the same idea works against HTTP/3, the newest version of the protocol that carries web traffic. A remote client with no login can send a small request and leave the server holding far more memory than the request weighed. FoxIO puts the multiple between tens and thousands of times. In its words, one connection is enough to exhaust or stall a default-configured server.

Seven of the ten implementations FoxIO tested are vulnerable. Several are already fixed. The Hacker News, which covered the disclosure, describes the impact as service disruption only. The outlet reports no sign of stolen data or injected code, and no attacks seen publicly.

How a small request becomes a large one

HTTP/3 shrinks request headers with a scheme called QPACK. Common headers travel as short codes. FoxIO gives an example: a 71-byte security header becomes a single byte, 0xFA, which points to an entry in a built-in table.

That saving is the risk. The server has to rebuild the full text, and it stores each header as an object in memory. The HTTP/3 standard (RFC 9114, Section 4.2.2) says servers should limit the unpacked size of a header list, counting 32 extra bytes of overhead per field.

FoxIO found implementations that got this wrong in at least one way. Some check only the compressed size. Some unpack everything before checking. Some leave out the 32-byte overhead. Some default to unlimited, and some do not enforce the setting at all.

Two ways to inflate a request

The first method sends many headers with unique names. FoxIO says a 1,000,000-byte frame holds about 160,000 of them.

The second method stores one large entry of about 4 KiB, then points to it thousands of times with one-byte references. Each reference makes the server copy the full entry again. FoxIO measured a ratio of 4,064 to 1 on lsquic and Bun. The Hacker News reports about 4,000 times on Bun and 600 to 1,800 times on lsquic.

What happened in each library

quic-go underpins Caddy, Traefik and cloudflared. Its HTTP/3 server limited the header frame to 1 MiB, but measured that size before unpacking. In FoxIO's test, a 1,000,000-byte block decoded into 160,075 fields and held about 15 MiB after garbage collection, roughly 15 times the bytes sent. The Hacker News adds that quic-go's own advisory (CVE-2025-64702) puts the expansion at around 50 times.

In Cloudflare's quiche (CVE-2026-12523), the size count left out the 32-byte overhead. FoxIO says that lets up to 33 times more headers through. With a 1 MiB limit, the standard allows about 32,000 headers, while quiche let about 1,000,000 one-byte headers pass. Quiche also reserved memory for a declared frame length before the data arrived. Version 0.29.3 fixes both.

lsquic had three problems that compound, FoxIO says. Fewer than 10 MiB of traffic across 50 connections held memory at a 5 GiB cap within a second. Version 4.9.0 fixes it.

Bun, which uses lsquic, replaced the library's header cap with its own code. That code checks each header but not the running total. Once decoded headers pass 2 GiB, a size counter wraps to zero and the server loops indefinitely. FoxIO says about 516 KiB on the wire leaves it at 100% CPU with no recovery. The Hacker News notes that Bun's documentation calls its HTTP/3 server experimental.

The Hacker News lists fixes for quic-go, quiche and lsquic as of October 22. Bun, the h3 Rust library and aioquic had none at disclosure. FoxIO lists IIS, Envoy and ngtcp2/nghttp3 as not affected.

Wireshark (CVE-2025-13945) is a different case. The Hacker News says its flaw crashes the HTTP/3 dissector, the part that reads a packet capture. It is not an internet-facing server that an attacker reaches over the network. A fix exists, but it does not belong in the count of vulnerable servers.

The lesson: an advertised limit is not a control

This shows a pattern beyond one protocol. A request passes through several layers. QUIC counts bytes. The QPACK decoder rebuilds fields. The HTTP/3 layer and the application turn them into objects and keep them. FoxIO says each layer can assume another one enforces the limit.

The evidence is in the settings. Bun advertises a header limit of 16,384 bytes but does not enforce it, FoxIO found. In nghttp3, the setting only signals a limit, and the application must enforce it. A configuration page that lists a limit can look reassuring while protecting nothing.

The risk lands on operators who did not write the library. They inherit it inside a proxy, a web server or a container, and they find out when memory runs out.

Questions to put to your team

Ask which HTTP/3 library each public service uses, and which version. FoxIO publishes JA4Scan fingerprints to help identify exposed servers. Libraries sit under products such as Caddy, Traefik, LiteSpeed and OpenLiteSpeed, so ask vendors whether their builds include the fixes.

Ask who owns the decoded header limit in each stack, and whether anyone has tested it. For unpatched software, FoxIO suggests turning off HTTP/3 in mitmproxy with --set http3=false, setting max_field_section_size in h3, and not exposing Bun's HTTP/3 server.

Finally, ask whether memory spikes on edge servers raise an alert before the process fails.

A size limit that is checked at the wrong point is only a label. Test the limit against what the request becomes, not what it weighs when it arrives.

Produced by the WebPulse Newsroom with AI assistance from the original reporting credited below, and checked against that source by our editorial review. How we use AI.
Original reporting: FoxIO.

Share this insight