Find Node.js runtimes and websites reporting a version affected by Node2Shell
CVE-2026-111497 · offline runtime assessment · passive, single-file, dependency-free
node2shell-check compares the Node.js version a runtime or website reports with the official upstream fix for each supported branch. Assess a version you already know, collect metadata inside a deployed service, or inspect a website's ordinary public response. It sends no exploit payloads, never decodes Brotli, and reports uncertainty honestly: a hidden, vendor-built, or conflicting version is unknown, never "safe".
git clone https://github.com/completetech-security/node2shell-check.git
cd node2shell-check
python node2shell_check.py --node-version 24.22.0 # offline, no network calls
node collect-runtime.cjs > runtime.json # run inside the deployed service
python node2shell_check.py --inventory runtime.json --format html --output report.html
python node2shell_check.py --input websites.txt --format html --output websites-report.htmlPython 3.10+ on Windows, macOS, or Linux. Nothing to install; use python3 where python is not Python 3. Node.js is needed only to run the optional collector.
--format html produces a single offline, script-free file with a logo, summary tiles, every result with its evidence and next step, and the upstream fix table. It follows the reader's light or dark theme and prints cleanly.
Synthetic example built from reserved example.* domains and invented runtimes. View the HTML.
Use --logo path/to/logo.png and --brand "Your Company" to brand it for your own organization. CSV and JSON remain available for spreadsheets and pipelines. --fail-on-finding exits 1 when any result is potentially_affected or unsupported_runtime; operational errors exit 2.
| Status | Meaning |
|---|---|
🔴 potentially_affected |
A plain Node.js version below its branch's fix is reported. Verify the deployed build and prioritize remediation. |
🟠 unsupported_runtime |
The version is on an older, unsupported upstream line. Verify vendor support and move to a supported, patched runtime. |
🟢 fixed_version_reported |
The reported version meets the fix. Not independent verification of installed patches. |
⚪ unknown |
Version missing, malformed, conflicting, vendor-qualified, custom-built, pre-release, possibly backported, or outside this rule snapshot. |
| Node.js branch | 22.x | 24.x | 26.x |
|---|---|---|---|
| Fixed in | 22.23.4 | 24.22.1 | 26.12.1 |
Thresholds come from the Node.js October 2026 security releases and the release notes for 22.23.4, 24.22.1, and 26.12.1, released 2026-10-21. The embedded rule snapshot is dated 2026-10-23.
Important
Potential exposure is not confirmed exploitability. Every result keeps exploitability not_tested. The vulnerability involves decoding attacker-controlled Brotli data, and a version alone cannot show whether an application reaches that code path. Treat every result as a prompt for an administrator to check.
- Known version:
--node-version(repeatable) compares a version you obtained elsewhere. No network calls. - Runtime inventory:
collect-runtime.cjsrecords version and build metadata from the Node.js binary that runs the service. It never loads application code, reads environment variables, decompresses data, or opens a connection, and it cannot attest vendor patch provenance. - Website metadata: reads
robots.txt, then makes an ordinaryGETrequest to the page if allowed, with verified TLS, an honest User-Agent, bounded responses, and pacing. Redirects stay on the same host or itswwwcounterpart, and HTTPS downgrades stop. It fetches nothing else and sends no compressed bodies, credentials, or crafted requests.
Input modes can be combined in one report; each observation keeps its own evidence. Express or Next.js hints never become Node.js version evidence, and Brotli response compression does not prove request decoding.
Check only targets you are authorized to assess, and keep real target lists, inventories, and results out of version control.
- Full reference: every CLI option, inventory field, output field, and request rule
- Assessment methodology: how each version is classified, with sources
- Exploit-specific checker repositories: roadmap for one independent repository per exploit
- Checker delivery status: dated merge/CI receipts and remaining roadmap scope
- Contributing · Security policy
python -m unittest -v # local-only tests; no external websites are contactedFor agents contributing to this repository, AGENTS.md contains the shared development instructions; CLAUDE.md points Claude to them.
Dual licensed: AGPL-3.0, including commercial use that meets its terms, or a commercial license from CompleteTech LLC for closed-source products and services that don't fit the AGPL model. See LICENSING.md for details. The CompleteTech LLC name and logo are covered by neither license; see BRAND_ASSETS.md.

Built by CompleteTech LLC · Innovation at Every Integration
An interruption after a complete report is published preserves that report and exits 130.
CSV rejects NUL characters before writing a report.
Report schema 1.1 records the executable SHA-256 and explicit
run completeness in JSON, CSV and HTML. Empty CSV reports contain a summary row;
existing observation columns and inventory schema 1 remain compatible.
Optional release tooling: offline TUF bundle verification uses separate optional dependencies and an explicitly provisioned public trust root. It never changes the standalone checker or automatically applies a rule update.
The optional authenticated rule-publication channel uses pinned GitHub/Sigstore publisher identity, expiring artifacts and durable rollback checks. Updates produce a separate review artifact; the checker keeps its embedded offline snapshot.
Optional family metadata tools: Node capability and build-context collection. These separate formats do not change the Node2Shell inventory schema or infer application exposure from available APIs, lockfile declarations or image tags.
