Back
28/10/2026
Node2Shell (CVE-2026-111497): which systems are at risk, and what to do now
Which systems CVE-2026-111497 in Brotli really exposes, how urgent each case is, and the steps to patch, rebuild, restart and mitigate now.
Updated 27 October 2026
CVE-2026-111497, nicknamed “Node2Shell” or “HTTP2Shell”, is a memory-corruption bug in the Brotli decompressor. Brotli is the br compression used across the web. The bug sits in Google’s Brotli library versions 1.0.3 through 1.2.0 [1]. Node.js bundles that library, and the Node.js project rated the issue High for the 22.x, 24.x and 26.x lines [2]. The same decoder ships inside Python packages, Linux system libraries, desktop apps and developer tools, so the real exposure is much wider than “Node.js servers”.
This article is for teams that need to decide quickly whether they are exposed and what to do first.
Bottom line: If any of your systems decompress Brotli data that comes from someone you don’t control (a client on the internet, an external website, a webhook sender, an uploaded file), treat this as urgent. Patch, rebuild, restart, and block br in the meantime.
What the vulnerability does
The decoder mishandles a malformed “block switch” in the compressed stream. It treats the error as “I need more input” instead of “this data is invalid”, and it keeps appending bytes to a small fixed internal buffer until it writes past the end [2]. An attacker who can get your application to decompress a crafted Brotli stream can corrupt process memory. That can lead to:
- A crash (denial of service). This is the most reliable outcome.
- Leaked process memory. Responses or logs could expose fragments of secrets, tokens or other users’ data.
- Possible remote code execution. Node.js lists RCE as a possible impact [2]. The first public proof of concept reached code execution only against a deliberately weakened build, but researchers have since reported unreliable code execution against an official, unmodified Node.js 24.22.0 build [3].
No authentication is needed: the attacker only has to deliver bytes that reach the decoder. That is why the CVSS 4.0 score is 9.2 (Critical) [1]. The key question for every system is therefore not “do we use Brotli?” but “can an untrusted party make us decompress Brotli?”
Typical usage cases and their risk
Case 1: Internet-facing APIs that accept compressed request bodies (highest priority)
Some Node.js API servers, BFFs, API gateways and upload endpoints decompress request bodies sent with Content-Encoding: br. Others do the same through middleware. Risk: any anonymous client on the internet can send a crafted body. Effects range from crashing the service repeatedly, which is a cheap DoS, to leaking memory from a process that holds session data and API keys. Urgency: emergency. Patch today, and block br request bodies at the edge until you have.
Case 2: Services that fetch content from outside (high priority)
Webhook consumers, crawlers and scrapers, link-preview and RSS services, payment or SaaS integrations, and AI agents that browse the web all make outbound HTTP requests. Many HTTP clients send Accept-Encoding: br and decompress the response automatically. In Python, urllib3 and requests do this whenever the Brotli or brotlicffi package is installed, even if your code never imports it. aiohttp does the same, and httpx does when installed with its brotli extra [4]. Risk: a malicious, compromised or spoofed remote server can attack your backend through its response. The attacker doesn’t need to reach your network at all: you call them. Urgency: high. Patch first wherever the destinations are not fully trusted.
Case 3: Desktop apps, AI coding agents and CLIs with an embedded runtime
Electron apps, Bun- or Node-based CLIs and AI developer tools carry their own copy of the runtime. Updating the system node package does not fix them. Updating the app on disk does not fix copies that are already running either: long-lived processes keep the old runtime in memory until they restart. Risk: these tools often hold credentials and fetch external content, which combines Case 2 with a privileged process. Urgency: high for tools that fetch untrusted content. Update them, then actually restart them. We covered the “updated but still running the old code” trap in detail in HTTP2Shell: why updating a binary does not remediate running processes.
Case 4: Container images and CI/CD artifacts
Images built FROM node:22, node:24 or node:26 before the fix still contain the vulnerable runtime, even if the host is patched. The same applies to bundled Python wheels and vendored dependencies. Risk: the vulnerable code returns on every deploy and every autoscaling event until the image is rebuilt. Urgency: high for images behind Cases 1 and 2. Rebuild rather than just restart.
Case 5: Linux system libraries, fonts and image processing
Distributions ship the decoder as a shared library, for example libbrotli1 on Ubuntu/Debian. It is used by curl and libcurl when compression is enabled, by FreeType for WOFF2 web fonts, and indirectly by image and document tools such as Pillow. Risk: systems that render user-uploaded fonts or documents, or that pull external content with curl --compressed, can be reached by untrusted Brotli data. A server that never feeds external data into these libraries has low practical exposure. Urgency: medium in most cases, but high for document-rendering or upload-processing services. Ubuntu has published fixed brotli packages for 22.04, 24.04, 26.04 and 26.10 [1]. For RHEL, Oracle Linux and other distributions, check your vendor’s advisory for the brotli package rather than assuming a status.
Case 6: Internal-only systems with trusted inputs (lower priority)
Some services decompress Brotli only from data you produce yourself, such as internal caches or your own build artifacts. These are lower risk, but not zero: an attacker who already has a foothold can use the bug to move further. Urgency: patch in the next regular cycle.
What to do: response steps
Step 1: Find where Brotli is decoded (today)
- Node.js: check
node -von every host, and in every container image and CI runner. Search code and configs forbrotliDecompress,createBrotliDecompressand body-parsing middleware that inflatesbr. - Embedded runtimes: list the Electron apps, Bun/Node CLIs and AI agents in use, and record the runtime version each one embeds, not just the app version.
- Python:
pip show Brotli brotlicffiin each environment and image. Look forhttpx[brotli]and transitive pulls in lockfiles and SBOMs. - OS packages:
dpkg -l | grep brotliorrpm -qa | grep brotli, then see which processes actually load the library. - Prioritize using the cases above: anything reachable by untrusted input (Cases 1, 2, 3 and 5 with uploads) comes first.
Step 2: Patch the affected components
- Node.js: upgrade to 22.23.4, 24.22.1 or 26.12.1 or later [2].
- Python:
Brotli>=1.2.1orbrotlicffi>=1.2.1.0. Regenerate lockfiles [4]. - Upstream Brotli / vendored C code: 1.0.10, 1.1.1 or 1.2.1, depending on the branch [1].
- OS packages: apply your distribution’s security update for
brotli/libbrotli. - Desktop apps and agents: update to vendor releases that state they include the fixed runtime. If a vendor has published nothing, treat the app as unverified rather than safe.
Step 3: Rebuild, redeploy and restart
- Rebuild container images from patched base images and redeploy. Restarting an old image does not help.
- Restart every long-running process that had the vulnerable library loaded: Node services, workers, agent sessions and anything linked against the system library. For stateful jobs and AI agents, drain or hand off work first so you don’t lose queued events or approvals.
Step 4: Mitigate while you patch
- Inbound: reject request bodies whose
Content-Encodingcontainsbrat the reverse proxy, load balancer or WAF, before any decoder sees them. - Outbound: removing
brfromAccept-Encodingis not enough on its own, because a malicious server can sendbranyway. Also reject or refuse to decode responses that arrive withContent-Encoding: br[4]. - Python fallback: where an upgrade must wait, uninstall
Brotliandbrotlicffiso clients stop decodingbr. Test first, because some servers will still sendbr.
Step 5: Verify, and watch for signs of exploitation
- Confirm the runtime version from inside the running process or container, not only from the package manager.
- Re-scan images and SBOMs to make sure no older copy is still being pulled in transitively.
- Review recent logs for unexplained crashes, segmentation faults or restart loops in services that handle
br. A cluster of crashes from a single source is worth investigating as an attempted attack. - If a high-exposure service crashed unexpectedly before it was patched, consider rotating the secrets that process held, since memory disclosure cannot be ruled out.
Summary
| Situation | Risk | Action |
|---|---|---|
Public API decodes br request bodies | Critical | Patch now; block br at the edge |
| Backend fetches external URLs, webhooks or web pages | High | Patch now; refuse br responses |
| Electron apps, AI agents or CLIs with an embedded runtime | High | Update and restart every running instance |
| Old container images and CI artifacts | High | Rebuild from patched bases and redeploy |
System library used for uploads, fonts or curl --compressed | Medium–High | Apply the OS update; restart the services that load it |
| Internal, trusted data only | Low–Medium | Patch in the next cycle |
Patching the package is only half the job. The exposure is gone only when no running process, image or embedded runtime can still decode untrusted Brotli with the old code.
Japan
Korea
China
Taiwan
Vietnam
Thailand
Indonesia
Portugal
Spain
France
Germany
Egypt
Russia