Safeguard
Vulnerability Analysis

HTTP/2 Rapid Reset (CVE-2023-44487) Explained

A protocol-level flaw in HTTP/2 turned a normal feature into the largest DDoS attacks ever recorded. Here is how Rapid Reset works and which library versions fix it.

Marcus Chen
Security Researcher
6 min read

CVE-2023-44487, better known as HTTP/2 Rapid Reset, is unusual among famous vulnerabilities because it is not a bug in any one product. It is a weakness in the HTTP/2 protocol itself, which means almost every modern web server, proxy, and load balancer that speaks HTTP/2 was affected at once. It carries a CVSS v3 base score of 7.5 (High), and despite that moderate rating it powered the largest volumetric denial-of-service attacks ever publicly recorded.

Timeline and impact

Google, Cloudflare, and Amazon jointly disclosed the technique on October 10, 2023, after independently mitigating attacks that had been running since roughly August 2023. The numbers were staggering: Google absorbed a peak of 398 million requests per second, Cloudflare 201 million rps, and AWS 155 million rps. For context, Cloudflare noted that this single attack was roughly three times larger than any it had seen before. CISA published an alert the same day, and vendors across the ecosystem shipped coordinated patches within hours.

The practical impact was resource exhaustion. A single attacker with a modest botnet could saturate a target's CPU and connection-handling capacity, taking down APIs, web front ends, and gateways without needing the massive bandwidth that older volumetric attacks required.

Root cause

HTTP/2 introduced stream multiplexing: a single TCP connection can carry many concurrent request streams, each identified by a stream ID. To keep servers from being overwhelmed, the protocol allows a server to advertise a limit on concurrent streams (SETTINGS_MAX_CONCURRENT_STREAMS, commonly 100 or 250). HTTP/2 also lets a client cancel a stream at any time by sending a RST_STREAM frame.

Rapid Reset abuses the gap between those two features. When a client cancels a stream, the server frees that stream slot immediately, so the cancellation does not count against the concurrency limit. An attacker opens a stream with a HEADERS frame, then instantly cancels it with RST_STREAM, then opens another, and so on. The concurrency ceiling never trips, because from the connection's point of view no stream is ever "in flight." Meanwhile the server has already begun the expensive work of dispatching each request to a backend before the reset arrives.

Conceptually the attacker loop looks like this:

for each connection:
  loop:
    send HEADERS  (stream N)   -> server starts request work
    send RST_STREAM (stream N) -> server frees the slot, work continues
    N += 2

The client spends almost nothing to send the two small frames; the server pays the full cost of routing, allocating, and cancelling a request. Multiply by hundreds of thousands of streams per second across many connections and you have request rates in the hundreds of millions.

Detection

Because Rapid Reset lives inside encrypted HTTP/2 connections, plain packet inspection is not enough. The signals to watch for:

  • A very high ratio of RST_STREAM frames to completed responses on HTTP/2 connections.
  • Streams whose lifetime, from HEADERS to RST_STREAM, is near zero.
  • CPU saturation on front-end servers that is disproportionate to observed completed-request volume.
  • Access logs showing large numbers of requests marked as client-cancelled or "499"-style statuses.

Most web servers and CDNs added per-connection reset counters and metrics after disclosure; alerting on an abnormal reset-to-request ratio is the most direct detection.

Remediation and patched versions

The durable fix is to bound the work an attacker can trigger by counting resets. Implementations now track the number of streams reset on a connection and close connections that reset streams faster than they complete them. Confirmed fixed versions include:

  • Go: golang.org/x/net/http2 v0.17.0, shipped in Go 1.21.3 and Go 1.20.10.
  • Netty: 4.1.100.Final.
  • Node.js: 18.18.2 and 20.8.1 (which bundle nghttp2 1.57.0).
  • Envoy: 1.27.1, with backports to 1.26.5, 1.25.10, and 1.24.12.
  • nginx, Apache httpd, and major CDNs shipped configuration and code mitigations in the same window; consult each vendor's advisory for exact builds.

As an interim mitigation where patching lagged, operators reduced SETTINGS_MAX_CONCURRENT_STREAMS, capped the number of new streams per connection, and rate-limited connections showing abnormal reset behavior. Since the vulnerability is in the protocol, disabling HTTP/2 was the last-resort mitigation but carried a real performance cost.

How Safeguard helps

Being honest about scope matters here: Safeguard does not sit inline as a DDoS scrubber, and it will not absorb an attack for you. What it does is solve the inventory problem that made Rapid Reset so painful to respond to, which was answering "where do we actually run a vulnerable HTTP/2 stack?" across dozens of services.

Because Rapid Reset was ultimately fixed in libraries like golang.org/x/net/http2, Netty, and nghttp2, it is a dependency problem, and that is squarely where a software composition analysis platform helps. Safeguard's software composition analysis resolves your full dependency graph and flags every service still pulling a pre-fix version of an affected HTTP/2 implementation, including deep transitive uses buried under frameworks. Because CI images and base images bundle these runtimes, container image scanning confirms whether a vulnerable Node.js, Go, or Netty build is baked into a shipped artifact. Where the fix is a straightforward version bump, automated fix pull requests move affected repositories onto patched releases, and Griffin AI helps triage which internet-facing services should be prioritized first. If you are weighing how different scanners surface a protocol-spanning issue like this, our comparison pages walk through the differences.

Frequently Asked Questions

Is CVE-2023-44487 a bug in a specific product? No. It is a design weakness in the HTTP/2 protocol's interaction between stream cancellation and concurrency limits. That is why so many independent products, servers, proxies, load balancers, and language runtimes, were all affected and had to patch simultaneously.

Why is the CVSS score only 7.5 if it caused record-breaking attacks? CVSS rates the vulnerability's intrinsic characteristics, and this is a denial-of-service issue with no confidentiality or integrity impact, which caps the score. The real-world severity came from how cheaply and massively it could be scaled, which CVSS does not fully capture.

Do I need to disable HTTP/2 to be safe? No, and you should not have to. The patched versions add reset-accounting that closes abusive connections while leaving normal HTTP/2 traffic intact. Disabling HTTP/2 was only ever an emergency stopgap for systems that could not be patched quickly.

How do I know if my applications are still exposed? Inventory every service that terminates HTTP/2 and check the version of its underlying implementation against the fixed releases above. This is far easier with a dependency graph than by hand, because the vulnerable code is often a transitive library rather than something you imported directly.

Get started at app.safeguard.sh/register, and find integration guides at docs.safeguard.sh.

Never miss an update

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