Safeguard
Vulnerability Management

HTTP/2 Rapid Reset: inside CVE-2023-44487

A single HTTP/2 feature let attackers hit 398 million requests per second. Here's how Rapid Reset (CVE-2023-44487) broke nearly every major web server at once.

Safeguard Research Team
Research
6 min read

On October 10, 2023, Google, Cloudflare, and AWS simultaneously disclosed a vulnerability that had already been exploited in the wild for two months, tracked as CVE-2023-44487 and nicknamed HTTP/2 Rapid Reset. The National Vulnerability Database describes it plainly: "request cancellation can reset many streams quickly," letting an attacker force server-side resource consumption without ever completing a request. It carries a CVSS v3.1 base score of 7.5 (HIGH) — network exploitable, no privileges or user interaction required, availability impact only — and maps to CWE-400, Uncontrolled Resource Consumption. CISA added it to the Known Exploited Vulnerabilities catalog with a federal remediation deadline of October 31, 2023. What made it unusual wasn't the CVSS number; it was the blast radius. The bug lived not in one product but in the HTTP/2 protocol's design, so it hit Node.js, Apache httpd, Tomcat, Nginx, Envoy, HAProxy, Go's net/http and gRPC stacks, Microsoft .NET and Azure, Kubernetes ingress controllers, and Cisco's NX-OS and IOS XE — essentially the entire modern web serving stack — within the same disclosure window. Google Cloud reported mitigating a related flood peaking at 398 million requests per second, the largest DDoS attack it had observed to that point. This post walks through why one HTTP/2 feature became a universal attack surface.

What in HTTP/2's design makes Rapid Reset possible?

HTTP/2's core innovation over HTTP/1.1 is stream multiplexing: a single TCP connection carries many concurrent "streams," each an independent request/response exchange, instead of one request per connection or a strict queue. To cancel a stream a client sends a RST_STREAM frame, and the protocol lets it do so at any time — including immediately after opening the stream, before the server has sent a response. That cancellation is cheap for the client but not for the server: by the time the reset arrives, the server has often already allocated a request object, spawned a handler thread or coroutine, and begun routing the request through application logic. RFC 7540 (HTTP/2, 2015) never anticipated this asymmetry being abused at volume. A client can open a stream and immediately reset it, then repeat that cycle thousands of times per second on one connection, and nothing in the base protocol requires a server to notice or throttle the pattern before it becomes damaging.

How does an attacker actually execute a Rapid Reset flood?

The attack script is simple: open an HTTP/2 connection, send a request HEADERS frame, then immediately follow it with an RST_STREAM frame canceling that same stream, and repeat in a tight loop — potentially thousands of open-then-cancel cycles per second per connection, multiplied across many connections. Because each stream is canceled before it completes, it never counts against traditional protections like "max requests per connection" or completed-request rate limits, which typically measure finished transactions, not attempted ones. Meanwhile the server still did real work per stream: parsing headers, allocating a stream object, and often dispatching to a backend worker before the cancellation frame is processed and cleanup runs. If stream creation and teardown cost more CPU or memory than the server can reclaim between cycles, memory and CPU usage climb even though the attacker's own traffic volume looks unremarkable — no completed requests, no obvious spike in successful responses, just a resource graph trending toward exhaustion.

Why did this affect almost every HTTP/2 implementation at once?

Because the flaw was in the shared assumption underlying nearly every HTTP/2 server implementation, not in one vendor's code: that stream cancellation is rare enough, and cheap enough, that it doesn't need independent rate limiting. Implementations differed in language and architecture but converged on the same gap. Node.js patched versions 18.0.0–18.18.2 and 20.0.0–20.8.1; Apache httpd, Tomcat, and Nginx shipped fixes to their HTTP/2 modules; Envoy and HAProxy patched their proxy layers; Go's net/http and golang.org/x/net/http2 (used by gRPC) shipped fixes; Microsoft patched .NET and Azure services; Cisco patched NX-OS, IOS XE, and Nexus platforms. Cloudflare, Google, and AWS each independently observed and disclosed the same pattern from live attack traffic in August through October 2023, which is why the coordinated multi-vendor disclosure landed on a single day rather than trickling out.

What stream-reset limits and connection policies stop it?

The fix vendors converged on is per-connection accounting of reset behavior, not just total request volume. Concretely: capping the number of RST_STREAM frames a single connection can send within a time window before the server closes it outright; lowering SETTINGS_MAX_CONCURRENT_STREAMS so fewer streams can be opened-and-canceled in parallel on one connection; and tracking the ratio of canceled-to-completed streams per connection, since a legitimate client rarely cancels more than a small fraction of what it opens. Several implementations also moved cleanup work earlier in the request lifecycle so a canceled stream frees resources before, rather than after, expensive backend dispatch. None of these mitigations require abandoning HTTP/2's multiplexing model — they just close the gap where cancellation was treated as free.

What should server operators do about it today?

The immediate, highest-leverage step is patching to the fixed versions of whichever HTTP/2 stack sits in front of your traffic — the affected-version lists above are a starting checklist, not exhaustive, so cross-reference your exact server, proxy, and load balancer versions against vendor advisories rather than assuming you're covered. Beyond patching, enable and tune stream-reset rate limiting where your server or CDN exposes it, and keep RST_STREAM-to-request ratios in your monitoring dashboards so a Rapid-Reset-style pattern shows up as an anomaly rather than blending into "normal" traffic that never completes. Because the technique bypasses request-completion-based defenses, a WAF or rate limiter configured only around successful responses won't catch it — visibility has to include canceled and incomplete streams, not just finished ones. For any team already running a vulnerability management program, CVE-2023-44487 is also a good test of process: it's a vulnerability with no code fix in your own application, only in third-party infrastructure, so tracking remediation means inventorying every HTTP/2-terminating component you operate — reverse proxies, ingress controllers, language runtimes, managed cloud load balancers — and confirming each one against its vendor's patched version, the same discipline used for tracking any other high-severity CVE through to closure.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.