Local inventory triage for Node2Shell, CVE-2026-111497. It finds every copy of the broken Brotli decoder already sitting on your machine or in your project, and grades it. It never touches the network, never sends a payload, never probes a server.
Detail |
Value |
|---|---|
CVE |
CVE-2026-111497 |
Also called |
Node2Shell, HTTP2Shell, Broccoli2Shell |
Bug |
Out-of-bounds write in the Google Brotli decoder (c/dec/decode.c) |
Impact |
Process crash, memory disclosure, or remote code execution when an app decompresses attacker-controlled Brotli data |
Severity |
9.2 critical (CVSS 4.0, Google as CNA) |
Exploitation |
CISA KEV, added 2026-10-27, federal due date 2026-11-10 |
Brotli 1.0.3 through 1.2.0 is affected. Node.js bundles that decoder, so any Node process that decompresses Brotli data it did not create is in scope: a request body through Express 5 / body-parser 2.x, which decode br bodies by default, or a fetched response through fetch() / node:zlib from a server you do not control. Just serving Brotli-compressed responses does not invoke the decoder, and a bare http server that never decompresses a body is not reachable this way. A version in range is triage, not proof your app is reachable. Check whether untrusted Brotli data ever reaches the process.
Two source disagreements, and what this scanner follows. On severity, Node.js rates the issue High, Google's CVE record scores it 9.2 critical, and Singapore CSA cites 9.8 under CVSS 3.1. This scanner follows the CNA score, 9.2, and says so. On exploitation, ELLIO's honeypots recorded exploit traffic on 2026-10-26 and ELLIO says the exploit gets a shell on vulnerable builds in its lab, while other reports of the same observed traffic say that attempt crashed the process instead of getting a shell. This scanner follows CISA KEV: exploitation is confirmed in the wild, the details are not public, and the observed-attempt argument does not change the patching advice.
Line |
Fixed in |
|---|---|
Node.js 22.x |
22.23.4 |
Node.js 24.x |
24.22.1 |
Node.js 26.x |
26.12.1 |
Node.js 20.x, 23.x, 25.x and older |
No fix, end of life, move to a supported line |
Bun |
1.4.4 |
Brotli library |
1.0.10, 1.1.1, 1.2.1 for their lines |
Python brotli |
1.2.1 |
Python brotlicffi |
1.2.1.0 |
Updating the runtime is the fix. Rebuild container images from a fresh base tag, redeploy, restart the process, then verify the running version. A pinned image tag stays vulnerable until it is rebuilt.
nodeandbunbinaries onPATH, plus any--scan-dirtree (nvminstalls included)Python brotli/brotlicffiin the current environment.nvmrcpins,package.jsonengines and body-parsing dependencies, andDockerfilenode:base-image tags in a project tree
Each finding gets a verdict: VULNERABLE, FIXED, EOL_NO_FIX, UNKNOWN, or INFO for project notes like Express 5 body decoding. Docker tags that pin a line but not a patch (node:24) grade UNKNOWN, because the patch they resolve to depends on when the image was built.
No network requests. No Brotli payloads, crafted or otherwise. No probing of remote servers, no 23 MB probes, no exploit traffic. It reads version strings off your own disk and stops.
Assetnote's free node2shell-scanner (released 2026-10-25) probes HTTP endpoints from the network, route by route. That is a good tool for the server side, and it is not this tool. It says itself it does not find fetchers or Python clients, and one clean route does not clear the others. This scanner covers the half it misses: the runtimes, libraries, and image pins sitting on disk, including the fetcher that decodes responses from servers you do not control. Use both. A clean network probe plus a clean inventory is a much stronger statement than either alone.
Finding |
Severity |
|---|---|
Node below its line's fixed patch, Bun below 1.4.4, Brotli in 1.0.3-1.2.0, brotlicffi below 1.2.1.0 |
VULNERABLE |
Node on an end-of-life line |
EOL_NO_FIX, counts as vulnerable, there is no patch coming |
Node at or past its line's fixed patch, and fixed Bun / Brotli / brotlicffi |
FIXED |
Floating Docker tag, line-only pin, unparseable version, or a Node line newer than 26.x |
UNKNOWN, not clean |
Express 5 / body-parser 2.x present, engines.node noted |
INFO, exposure context only, not a verdict |
# Inventory this machine: PATH runtimes, Python packages, current project
python3 node2shell_inventory_scanner.py
# Inventory a project tree, machine-readable output
python3 node2shell_inventory_scanner.py --scan-dir /srv/myapp --json
# Scan a tree only, without PATH runtimes
python3 node2shell_inventory_scanner.py --scan-dir ~/projects/api --no-path
# Tests (fake binaries and fake project trees only, no network)
python3 -m unittest discover -s tests -v
Exit codes: 0 = nothing vulnerable found, 2 = vulnerable or end-of-life finding, 1 = scan error. UNKNOWN does not change the exit code, but it is not clean. Confirm those items another way before closing them.
- A version in range is triage, not proof of exploitability. The app must actually decompress attacker-controlled
Brotlidata for this flaw to be reachable. - For
Bun, the fix version1.4.4is well attested, but the exact affected floor forBunis not stated in the advisory text this scanner verified, so anything below1.4.4gradesVULNERABLEconservatively. - A
Node.jsinstalled from a distribution package may use the systemBrotlilibrary instead of the bundled copy. The scanner flags distribution paths with a note: check the distributionbrotlipackage too. Dockertags lie by omission.node:24built before the fix andnode:24built after it share a tag. Rebuild with--pulland verify the running version.- This scanner does not inventory vendored
Brotlicopies inside other binaries (.NET,Envoy,Istio, firmware, data tools). Those need their vendors' advisories. - No exploit code is included, linked, or reproduced here.
Node.jsOctober 2026 security releases (fixed22.23.4,24.22.1,26.12.1)CVE-2026-111497record (Brotli 1.0.3-1.2.0affected, fixed1.0.10/1.1.1/1.2.1,CVSS 4.0 9.2)CISA KEVentry (added2026-10-27, due2026-11-10, ransomware use unknown)Assetnote node2shell-scanner(network-side check this tool deliberately complements, not duplicates)
- The
Node.jsmaintainers for the advisory and the fixed releases - The
Brotlimaintainers for the decoder fix ELLIO,Imperva, and everyone publishingNode2Shelldetection research
Built for defensive triage and authorized testing only. Scan only systems you own or are authorized to test. The authors are not responsible for misuse.
Research by
Vineeth Kumar(foxcornlab). Found a bug or want a feature, open anissue.