CVE-2026-105297: Pingora HTTP/2 server memory exhaustion through unbounded default header-list and concurrent-stream limits
Summary
Before version 0.8.1, Pingora's HTTP/2 server used the h2 crate's default limits unless the application set its own 16 MiB decoded header-list size and no limit on concurrent streams. A remote, unauthenticated client can send 1-byte HPACK references to a near-empty header, making the server allocate hundreds of thousands of header fields per stream across an unlimited number of streams on one connection, and use HTTP/2 flow control to keep those streams open. This can exhaust memory and degrade or terminate the Pingora process.
Impact
Remote, unauthenticated denial of service against any Pingora service that terminates HTTP/2 (h2 or h2c) without explicitly setting maxheaderlistsize and maxconcurrentstreams. The reporter showed that a single connection could get a Pingora process with a 2 GiB memory limit OOM-killed.
Note that Cloudflare CDN customers were unaffected, as internal Pingora services at Cloudflare do not have HTTP/2 clients.
Mitigation:
Upgrade to pingora 0.8.1 or later (fix: https://github.com/cloudflare/pingora/commit/d193c8d49b8b7c1c1ede93183759caa4f6906bbd ). When no H2Options are supplied, Pingora now advertises and enforces a 64 KiB decoded header-list limit and at most 100 concurrent streams per connection.
Applications that supply their own H2Options are not covered by these defaults and must set maxheaderlistsize and maxconcurrentstreams explicitly (this also works on versions before 0.8.1), or, on 0.8.1 and later, start from pingoracore::protocols::http::v2::server::defaulth2options(). H2Options::default() does not include these limits.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
Pingorato a version that resolves this vulnerability.Fixed in 0.8.1 - Configuration
For applications supplying their own H2Options, explicitly set max_header_list_size to 64 KiB and max_concurrent_streams to 100; on version 0.8.1 and later, alternatively start from pingora_core::protocols::http::v2::server::default_h2_options().
Pingora HTTP/2 server H2Options max_header_list_size and max_concurrent_streams = 64 KiB and 100
Event History
Frequently Asked Questions
Which deployments are exposed?
Any Pingora service that terminates HTTP/2, including h2 or h2c, is affected before version 0.8.1 if it does not explicitly set both max_header_list_size and max_concurrent_streams. Cloudflare CDN customers were not affected because Cloudflare's internal Pingora services do not have HTTP/2 clients.
What does an attacker need to exploit this?
An attacker only needs network access to the service's HTTP/2 endpoint; authentication and user interaction are not required. A single HTTP/2 connection can use small HPACK references, unlimited streams, and flow control to retain allocated header fields.
Are default settings affected?
Yes. Before version 0.8.1, Pingora used the h2 crate defaults when an application did not supply H2Options, including a 16 MiB decoded header-list size and no concurrent-stream limit.
What should be done if the service cannot be upgraded immediately?
Explicitly configure max_header_list_size and max_concurrent_streams for HTTP/2 rather than relying on the defaults. The documented permanent mitigation is upgrading to Pingora 0.8.1 or later; when no H2Options are supplied, that version enforces a 64 KiB decoded header-list limit.
What indicates active impact?
The affected Pingora process may show rapidly increasing memory use, degraded service, termination, or an OOM kill. The reported demonstration caused a process limited to 2 GiB of memory to be OOM-killed using one connection.