fix: use HeaderMap::try_append to prevent panics on absurd amounts of headers#909
Conversation
|
We've encountered this issue in production as well. |
Thanks for confirming this! It's incredibly valuable to know that this is being encountered in real-world production environments and is not just a theoretical edge case. I actually stumbled upon this panic vector while doing research on CVE-2026-53948 (the HPACK / HTTP/2 Bomb vulnerability class). Since you are running |
I'm not familiar with CVE-2026-53948 for now; I suggest adding a test in this PR to verify the fix works. |
|
The HPACK bomb is something different. It hopes to decode small wire payloads into tons of memory and OOMKill the process. h2 enforces max size limits. What you've triggered is a different case, simply a hard limit on the number of header fields the Though, there's a few other things that protect a server from this:
|
326b11e to
112730c
Compare
|
Hi @seanmonstar, this pr is ready to review now. And here's a summary of the changes:
The |
|
Yea, I'm fixing up any other CI failures. I'm very confused why the |
|
Oh my bad, I don't know why I didn't notice, the style check is failing something in this PR. If you run |
…S panic HeaderMap::append() panics when inserting >24,576 unique header fields (size overflows MAX_SIZE), allowing an unauthenticated remote attacker to crash the server with a single request containing enough unique headers. Replace with try_append() and set is_over_size on Err, so the existing is_over_size check in recv.rs properly rejects the stream (RST_STREAM / HTTP 431) instead of panicking.
The try_append method was added in http 1.1.0. Without this bump, the minimal-versions CI job resolves http to 1.0.0 which lacks the method, causing compilation failure.
8b07825 to
ef51cf1
Compare
|
@seanmonstar I've fixed with |
Summary
Replace
HeaderMap::append()withHeaderMap::try_append()in the HPACK decode callback (src/frame/headers.rs:914) to prevent a remote DoS.Problem
An unauthenticated remote client can crash any h2-based server by sending a single HTTP/2 request with >24,576 unique header fields.
HeaderMap::append()panics with"size overflows MAX_SIZE"when its internal hash table capacity is exceeded — this is a process-level panic that terminates all connections.max_header_list_sizedefault is 16 MB, which allows ~524,288 headers at 32 bytes eachHeaderMappanics at 24,576 unique keys — more than 20× below the configured budgetFix
When
is_over_sizeis set, the existing logic inproto/streams/recv.rs:204handles the error at the stream level (RST_STREAM / HTTP 431), keeping the connection alive.Impact
https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=1afcbbde1795302003479d26e0b2801f