What Happened: Two Separate HTTP/2 Bugs
Node.js released fixes for 16 vulnerabilities in a batch that affected multiple supported release lines. The two most critical flaws exist within the HTTP/2 implementation, which is built directly into the Node.js runtime. The first bug allows any unauthenticated client to send specially crafted requests that cause an HTTP/2 server to crash, triggering a denial of service. The second flaw is more insidious: it causes the server to leak pieces of its memory to clients, potentially exposing responses intended for other connections or other users entirely.
Both vulnerabilities affect the 24.x and 26.x release lines. The crash bug also impacts servers running on version 18.x in certain configurations. No version is bulletproof; even long-term support branches required patching. The fixes were distributed across three patch versions: 22.23.5 for the 22.x line, 24.22.3 for the 24.x line, and 26.13.1 for the 26.x line.
Why HTTP/2 Is a Wider Attack Surface
HTTP/2 is a protocol designed to improve web performance by multiplexing requests over a single connection and using binary framing instead of the plain-text headers of HTTP/1.1. This efficiency comes with architectural complexity. Node.js implements HTTP/2 directly in the runtime, which means flaws in that implementation bypass many of the hardening layers that exist in reverse proxies like nginx or Apache.
Many developers enable HTTP/2 without fully understanding the protocol's state machine and connection management. When a protocol parser contains a flaw, especially in memory handling, the consequences can cascade. A crash vulnerability in HTTP/2 is often simpler to trigger than in HTTP/1.1 because HTTP/2 frames are binary and easier to craft maliciously. The memory-leak bug is particularly concerning because it suggests improper buffer handling when switching between multiplexed streams.
The Crash Mechanism: How Attackers Trigger It
The denial-of-service flaw works by sending a sequence of HTTP/2 frames that violate the protocol's state machine or exceed the server's internal resource limits in a way the parser does not properly handle. An unauthenticated attacker can send these frames from any client, including a simple curl command or a custom script, and the server process terminates.
This is different from a memory exhaustion attack because the crash is instant and deterministic. The attacker does not need to fill memory gradually; the malformed frame sequence triggers an immediate null-pointer dereference or assertion failure in the HTTP/2 parsing code. For production systems, this means a single request can take down the entire application until it is restarted. Load balancers may attempt to route traffic to a healthy instance, but if all instances are vulnerable, the entire service goes dark.
Memory Leakage: Why Other Clients' Data Was Visible
The memory leak flaw is more sophisticated. HTTP/2 multiplexes many requests over a single connection, and the Node.js implementation manages buffers to hold response data for each stream. If the code that clears or segregates buffers between streams contains a flaw, one client can read data intended for another.
This could mean that a client's malicious HTTP/2 request causes the server to allocate or reuse a buffer that still contains another client's previous response. When the attacker's response is sent, it includes fragments of the leaked data. In a multi-tenant environment, this could expose API keys, session tokens, or sensitive query results. The vulnerability does not require authentication because it exploits a logic error in memory management, not an authorization check.
Who Was at Risk Before Patching
Any developer running Node.js 24.x or 26.x in production with HTTP/2 enabled was affected by both flaws. This includes applications that explicitly call `http2.createSecureServer()` or use frameworks like Express with HTTP/2 plugins. Developers on the 22.x branch were exposed only to the crash vulnerability, not the memory leak.
However, many developers do not realize they have HTTP/2 enabled. Some web frameworks or dependency packages enable it by default if the underlying Node.js version supports it. Others use HTTP/2 through a reverse proxy in front of Node.js, which shifts the risk to the proxy layer but does not eliminate the vulnerability if the proxy forwards HTTP/2 directly to the Node.js app. Checking your `http.createServer()` or framework documentation is the first step to determining your exposure.
Patching Strategy and Verification
The patches were released as minor version updates, not major changes, so upgrading should be low-risk from a compatibility standpoint. However, you must verify which version you are currently running and which line you track.
Run the following command to check your Node.js version:
- Open a terminal and enter `node --version` or `node -v`
- Compare the output against the three patched versions: 22.23.5, 24.22.3, 26.13.1
- If your version is below one of these, upgrading is required
- If you run multiple Node.js instances or use a container image, check all of them
- After upgrading, restart your application and verify it connects to clients without crashing
Many teams use Node.js within Docker containers. If so, rebuild your image with the patched version, re-push it to your registry, and redeploy. Kubernetes users can force a rolling restart of pods to pick up the new image. For bare-metal or virtual machine deployments, update Node.js directly and restart the service.
Reality Layer: What Actually Protects You
Reverse proxies like nginx or Apache can provide a layer of defense by handling HTTP/2 termination and forwarding HTTP/1.1 to your Node.js backend. This architecture means a bug in Node.js's HTTP/2 parser is never triggered because the proxy speaks HTTP/2 to the client and HTTP/1.1 (or HTTP/2) internally. If your production setup already uses this pattern, your exposure is lower, though not zero if you have internal services speaking HTTP/2 directly. Law enforcement and security vendors have documented that memory-leak vulnerabilities in protocol parsers are frequently exploited by state-level adversaries to harvest sensitive data from cloud infrastructure, so even a theoretically obscure bug can have real consequences.
Disabling HTTP/2 entirely in your Node.js configuration is another option if you do not need the performance benefits and want to reduce the attack surface. This is a valid trade-off for teams with simpler requirements. The HTTP/1.1 implementation in Node.js has been more battle-tested and has fewer known vulnerabilities.
Next Steps: Audit and Deploy
The most important action is to upgrade to the patched versions immediately in all environments: development, staging, and production. Do not delay this for a maintenance window if possible; treat it as a critical patch because both flaws allow either denial of service or data exfiltration without authentication.
After upgrading, review your Node.js HTTP/2 configuration. If you do not explicitly need HTTP/2, disable it. If you do use it, confirm that you are not passing sensitive data over HTTP/2 connections from untrusted clients until your team has had time to audit the security implications. Consider enabling HTTP/2 only on internal services behind firewalls or VPNs, not on public-facing endpoints, while you gain confidence in your patched version. Check the Node.js security release page and subscribe to notifications so you catch future vulnerabilities before they become incidents.
Source: The Hacker News
