HTTP2Shell: How a Brotli Flaw Became RCE, and the Fix
HTTP2Shell, also called Node2Shell, is the nickname for CVE-2026-111497, an out-of-bounds write in Google’s Brotli decompression library. Fixes shipped on 21 October 2026. Any service that automatically decodes Content-Encoding: br traffic can be pushed into corrupting its own memory, and from there into running attacker commands.
This post walks the attack chain and the response that actually contains it. Everything here mirrors our free HTTP2Shell RCE exercise, where you play both the attacker and the platform engineer on call.
What is HTTP2Shell?
Section titled “What is HTTP2Shell?”HTTP2Shell is a memory corruption flaw in the Brotli decoder, not in HTTP/2, despite the name. A malformed br stream makes the decoder write past the end of its buffer. With enough attempts, that overrun can steer execution instead of just crashing the process.
The decoder sits underneath the application. No login, upload form or vulnerable plugin is needed. Any endpoint that accepts a compressed body is a valid target, and so is any outbound fetch that decodes a compressed response.
How does an HTTP2Shell attack work?
Section titled “How does an HTTP2Shell attack work?”Exploitation is opportunistic. Attackers scan for services on a vulnerable build and work through whatever answers. The exercise follows Larksend, a fictional link-preview and webhook API, through four stages.
- Fingerprint. A plain request to a health endpoint names the runtime and framework, which tells the attacker the bundled Brotli is old.
- Fire. A br-encoded request body hits the API. Most attempts only crash a worker, which matches what the advisory describes.
- Land. On a later attempt the overrun runs a command as the
nodeprocess instead of crashing it. - Loot. The attacker reads the process environment and leaves with a live deploy token that can push to production.
Crash loops are the visible symptom. The token theft is the part that leaves no trace in the logs.
Is blocking br at the edge enough to stop HTTP2Shell?
Section titled “Is blocking br at the edge enough to stop HTTP2Shell?”No. An edge rule that rejects Content-Encoding: br stops inbound request bodies, and that is worth doing while you patch. It does nothing for responses your own services fetch.
Larksend’s preview worker fetches other people’s URLs and decodes whatever compression they send back. An attacker who controls one of those URLs reaches the same decoder from the inside. Dropping br from your Accept-Encoding header does not help either, because a hostile server can send br anyway. This is the same trust problem behind server-side request forgery: anything your service fetches is attacker input.
Why is the patched system package not the fix?
Section titled “Why is the patched system package not the fix?”Because the vulnerable copy of Brotli is bundled inside the runtime. Node ships its own Brotli, and so do many Python HTTP stacks, container images and vendor appliances. In the exercise, apt reports a patched libbrotli on the host while the API stays exploitable.
The proof is the runtime itself. Check node --version against the fixed release, and check the library version inside each worker image, not on the host. Our components with known vulnerabilities exercise drills the same inventory habit for application dependencies.
How do you fix HTTP2Shell?
Section titled “How do you fix HTTP2Shell?”The fix is an upgrade and a redeploy on every decode path. Fixed Brotli builds are 1.0.10, 1.1.1 and 1.2.1.
- Upgrade each runtime that bundles Brotli. Move the API image to the patched Node build and bump the worker’s bundled Brotli.
- Rebuild and redeploy every replica. Patching a running container is lost on the next restart. The vulnerable base images exercise shows how an old runtime hides in a layer.
- Prove it. Replay the request that crashed a worker and confirm the decoder now rejects it cleanly.
The same “installed is not running” trap caught teams during PHP2Shell a week earlier. Our zero-day patch management guide covers the verify step in more depth.
What should you do if a process was already reached?
Section titled “What should you do if a process was already reached?”Rotate every secret that process could read. A memory read leaves no log entry, so you cannot prove a token was not taken. Patching the runtime does not un-leak a credential.
In the exercise that means revoking the deploy token and staging a new one. The leaked access tokens exercise covers how to rotate without breaking production. Our post on secrets in Git and CI/CD explains why long-lived tokens in environment variables widen the blast radius.
If personal data was reachable, route it to your data protection team now. Under GDPR Article 33 the 72-hour clock starts when you become aware of a breach.
Why train on real incidents like HTTP2Shell?
Section titled “Why train on real incidents like HTTP2Shell?”Library flaws follow one shape: a dependency nobody thinks about, every stack that bundles it, and a fix that has to land in many places at once. Engineers who have rehearsed scoping, patching, verifying and rotating make fewer mistakes when the alert fires.
The Real-World Incidents catalogue turns breaches like this one into hands-on exercises, next to the PHP2Shell RCE walkthrough. Want your platform team drilled on the next library zero-day before it lands? Talk to us about rolling out incident-based training.