DEV Community

Bogdan Ionita
Bogdan Ionita

Posted on Originally published at relvato.com

Node2Shell (CVE-2026-111497): which Node.js versions fix it and where Node hides

Node2Shell is the name researchers gave CVE-2026-111497, a flaw in the Brotli decoder that ships inside Node.js. On 21 October 2026 the Node.js project fixed it in 22.23.4, 24.22.1 and 26.12.1. An app that decompresses Brotli data someone else can supply, such as a compressed request body or a response fetched from another server, can crash, leak memory or run an attacker's code. The fix is in Node.js itself, so npm update doesn't apply it: the runtime has to be upgraded everywhere it runs.

What Node2Shell is

Brotli is a compression format that web servers and browsers use alongside gzip. Node.js bundles a Brotli decoder in node:zlib. The Node.js advisory describes the bug: an invalid block switch in a compressed stream was treated as a temporary need for more input instead of a format error, so the decoder kept appending bytes to an eight-byte internal buffer and wrote past its end. Memory corruption like that can crash the process, leak memory, or let an attacker run code.

Node.js rates it high and says it permits remote code execution. It was reported by OpenAI Codex Security. Imperva's researchers then reproduced it as code execution without authentication, and proof-of-concept code is public, so treat every unpatched Node.js service that handles outside data as a target.

Are you exposed?

A Node.js process is exposed when it, or a library it uses, decompresses Brotli data that an attacker controls. Imperva tested two common ways that happens.

Incoming requests. Express 5 and body-parser 2 decompress request bodies sent with Content-Encoding: br, because body-parser's inflate option is on by default. So an app with app.use(express.json()) can be reached by a single crafted request, before any login.

Outgoing requests. Node's built-in fetch() asks for and decompresses Brotli responses on its own. Any server your code calls that an attacker controls or has compromised can reach the decoder: webhooks you call back, link previews, scrapers, AI agents that fetch the pages a user gives them, health checks of other sites.

Code that calls the Brotli functions in node:zlib directly on outside data is exposed the same way. Firewalls in front of your app only see the first path: they can't inspect what your code fetches from elsewhere.

Which versions fix it

Each supported Node.js line has one release with the fix (the table below). The same release also fixes nine other vulnerabilities, including three TLS certificate and DNS bugs rated high, so it's worth taking even if your app never touches Brotli.

Node.js 20 and older get no fix: they're past end of life, and the Node.js project says end-of-life versions are always affected when a security release ships. Bun, which bundles its own Brotli decoder, fixed the same flaw in 1.4.4.

Where Node.js hides

The upgrade has to reach every copy of Node that runs your code, and there are usually more than one.

Container images. A Dockerfile pinned to an exact version, such as node:24.22.0, stays vulnerable however often you rebuild it: move the pin to 24.22.1 or later. Base images that bundle their own Node (browser-testing images, for example) pin whatever was current when they were built, so upgrade Node inside them too.

Servers and CI. Node installed with nvm, a package manager or a CI setup action is upgraded there, then the service restarted.

Hosting platforms. Vercel deployed firewall rules against the incoming path for every project on 21 October and manages patch versions for its Node.js 22.x and 24.x runtimes, so those projects need no version change. Projects still on Node.js 20 must switch to 22.x or 24.x and redeploy. Vercel also notes its firewall doesn't cover responses your functions fetch from other servers. On other hosts, check the platform's own notice for which Node version your functions run.

Apps built with AI. If an AI app builder or coding agent wrote your app's server code, the question is the same: which runtime runs it, and at which version. See monitoring for AI-built apps for what else to watch once it's live.

How to check

Run node --version on laptops, CI runners and servers, and docker run --rm <image> node --version for each container image. In a running service you can log process.version at startup. Anything below the fixed release for its line, or on Node.js 20 or older, needs upgrading.

If you can't update today

Upgrading is the fix. Until it's rolled out, you can narrow the incoming path: refuse requests with Content-Encoding: br at your proxy or firewall, or set inflate: false on body-parser and express.json(), which rejects every compressed request body (check first that none of your clients send them).

There's no setting that protects the outgoing path, because a malicious server can send a Brotli response whatever your code asks for. Avoid fetching untrusted URLs from unpatched services until they're upgraded.

Runtimes with the Node2Shell fix

Runtime Fixed in Note
Node.js 26 26.12.1 Current release line
Node.js 24 24.22.1 LTS
Node.js 22 22.23.4 LTS
Node.js 20 and older No fix End of life: upgrade to 22 or 24
Bun 1.4.4 Bundles its own Brotli decoder

Questions, answered

Does npm update fix Node2Shell?

No. The flaw is in Node.js itself, not in a package, so updating dependencies doesn't change it. Upgrade the Node.js runtime to 22.23.4, 24.22.1 or 26.12.1 or newer wherever your code runs, then restart or redeploy.

I don't use Express. Am I safe?

Not necessarily. Node's built-in fetch() decompresses Brotli responses by default, so code that fetches from servers you don't control is exposed whatever framework you use. Upgrade Node anyway.

My app is on Vercel. Do I need to do anything?

On Node.js 22.x or 24.x, Vercel manages the patch version and has firewall rules against malicious request bodies, so no version change is needed. On Node.js 20, switch to 22.x or 24.x and redeploy. Vercel's firewall doesn't cover responses your functions fetch from other servers.

I'm on Node.js 20 or 18. What now?

They get no fix: both are past end of life. Upgrade to Node.js 22 or 24, test, and redeploy.

Does a web application firewall protect me?

Only against crafted requests coming in. It can't see the responses your code fetches from other servers, which is the other way in. Rules buy time; the upgrade is the fix.

Sources

Top comments (0)