FIXED SCOPE
AI & System Readiness Audit

Architecture review, risk surface, prioritised action plan. No obligation.

PAID - 2 WEEKS
Sharp Sprint

Fixed scope, senior engineers, working software. Skip the long discovery.

Contact us
Home → AI → CVE-2026-111497: Check and Patch the Node.js Brotli RCE (Node2Shell)

CVE-2026-111497: Check and Patch the Node.js Brotli RCE (Node2Shell)

Posted:
Updated:
TL;DR
  • CVE-2026-111497 is an out-of-bounds write in the Brotli decoder bundled with Node.js 22, 24, and 26. The Node.js project fixed it on October 21, 2026 in 22.23.4, 24.22.1, and 26.12.1; CISA added it to the Known Exploited Vulnerabilities catalog on October 27, 2026.
  • Treat it as exploited: inventory every host, container, CI runner, and laptop that runs Node.js, move each to the latest release in its line (22.23.4, 24.22.2, or 26.13.0 as of 2026-11-05), rebuild every container image, and prove it with node –version. Node 20 and older lines get no fix. Bun needs 1.4.4 or newer.
two-panel winnie the pooh meme: top panel reads 'from node:24', bottom panel reads 'from node:24.22.2-slim (pinned, pulled fresh, verified)' highlighting best-practice image says to pin and verify images.

Status on 2026-11-05: exploited, fixed, and unfixable on EOL lines

The Node.js Brotli vulnerability is confirmed exploited in the wild, fixed in every supported Node.js line, and unfixable on end-of-life lines. Copy the table into your incident ticket; every row links to its primary source. If a “node js vulnerability 2026” search brought you here, this is the one to act on first—and the response process below also applies to the next node js vulnerability 2026 brings.

ItemStatusSource and date
ExploitationConfirmed in the wildCISA KEV, added 2026-10-27; corroborated by Sysdig (ELLIO, Oct 26) and Datadog (Oct 29)
CISA KEV due date2026-11-10 for US federal civilian agencies under BOD 26-04CISA KEV, catalog version 2026.11.04
SeverityNode.js project: High. Google (CNA): 9.2 Critical, CVSS 4.0. NVD: 9.8 Critical, CVSS 3.1Node.js advisory, 2026-10-21; CVE record, updated 2026-10-27; NVD, modified 2026-11-04
Affected supported lines22.x, 24.x, 26.x before the fixed buildsNode.js advisory, 2026-10-21
Minimum fixed versions22.23.4, 24.22.1, 26.12.1Node.js advisory, 2026-10-21
Latest supported releases22.23.4, 24.22.2, 26.13.0Node.js dist index, snapshot 2026-11-05
End-of-life lines25.x, 23.x, 21.x, 20.x, 18.x, 16.x: affected, no patchNode.js releases page, 2026-11-05
BunAffected 1.0.21 through 1.4.3; fixed in 1.4.4Bun advisory, 2026-10-23
Next security releaseHIGH-severity release for 22.x, 24.x, 26.x on or after 2026-11-11Node.js pre-announcement, updated 2026-11-03

Re-check CISA KEV and the Node.js vulnerability blog before circulating internal guidance.

What is CVE-2026-111497 (Node2Shell)?

CVE-2026-111497 is an out-of-bounds write in the Google Brotli decoder (Brotli 1.0.3 through 1.2.0) that Node.js bundles for node:zlib. A crafted Brotli stream corrupts decoder memory, which can crash the process, leak memory, or run attacker-supplied code. Google fixed the library in Brotli 1.2.1 on October 21, 2026, and Node.js shipped the fix the same day.

The Node.js advisory describes the mechanism: “An invalid block switch was reported as a temporary need for more input instead of a permanent format error, so the streaming decoder kept appending input bytes to an eight-byte internal buffer.” The patched decoder rejects that state with a new error, BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH. OpenAI Codex Security reported the flaw.

Two nicknames circulate: “Node2Shell” is Imperva Red Team’s label for its October 22 analysis, and “HTTP2Shell” is Aikido’s label for the wider blast radius. Neither is official, and HTTP/2 isn’t required to trigger the bug. Severity has three answers from three authorities (Table 1); quote the authority with the number.

infographic slide titled exposure path showing four brotli decoder vulnerability steps: 01 untrusted brotli input → result: attacker-controlled stream; 02 decompression in the bundled decoder; 03 out-of-bounds write; 04 process impact and related risks.
exposure starts when attacker controlled brotli data reaches the decoder through a body parser an outbound fetch or a direct node zlib call and ends in a crash memory disclosure or code execution

Which Node.js versions are affected, and which fix it?

Every release in the 22.x, 24.x, and 26.x lines before 22.23.4, 24.22.1, and 26.12.1 is affected, and every end-of-life line is affected at every patch level. The minimum fixed builds shipped on October 21, 2026; the latest supported releases on 2026-11-05 are 22.23.4, 24.22.2, and 26.13.0. Install the latest release in your line, not the bare minimum.

LineLifecycle (2026-11-05)Minimum fixed versionLatest supported releaseAction
26.x “Lithium”LTS26.12.126.13.0 (2026-10-28)Update to 26.13.0
24.x “Krypton”LTS24.22.124.22.2 (2026-10-27)Update to 24.22.2
22.x “Jod”LTS22.23.422.23.4 (2026-10-20)Update to 22.23.4
20.x “Iron”End of lifenonenoneMigrate to 22.x or 24.x
25.x, 23.x, 21.x, 18.x, 16.xEnd of lifenonenoneMigrate to a supported LTS line
27.xAlpha, not for productionn/an/aKeep out of production

Minimum fixed versus latest supported Node.js releases. Sources: Node.js advisory (2026-10-21); Node.js dist index and releases page (snapshots 2026-11-05). Dates are dist-index build dates.

Node 20 is end of life, and it’s the line many teams still run. The Node.js advisory treats end-of-life lines as affected by every security release, and Vercel’s bulletin puts it plainly: “Node.js 20 reached end of life and will not receive this fix.” Your options are a migration to 22.x or 24.x, or a commercial extended-support contract that backports fixes while you migrate.

comparison of minimum fixed release vs latest supported release with node versions listed (22.23.4, 24.22.1, 26.12.1 vs 22.23.4, 24.22.2, 26.13.0)
the minimum fixed nodejs builds are 22234 24221 and 26121 while the latest supported releases on november 5 2026 are 22234 24222 and 26130 end of life lines get no fix

Is CVE-2026-111497 being exploited in the wild?

Yes. CISA added CVE-2026-111497 to the Known Exploited Vulnerabilities catalog on October 27, 2026, which means CISA holds evidence of exploitation in the wild. The entry sets a required-action date of November 10, 2026 for US federal civilian agencies under BOD 26-04: a useful benchmark for a private company’s timeline, not a legal obligation outside those agencies.

Write-ups from the first 48 hours said otherwise, and some are still being quoted. Sysdig’s October 28 update superseded its own earlier assessment: “On October 26, ELLIO confirmed exploitation.” Datadog Security Labs corroborated on October 29. An internal memo that cites the earlier status is stale.

The exploit is real but not trivial. A public proof of concept appeared on October 22, 2026; on standard builds it produces a crash and a limited memory read, per Datadog. Imperva ran code inside the official Node.js 24.22.0 image behind Express 5 and noted that “execution took multiple attempts.” A crash-only attempt is still an outage, so unreliable RCE doesn’t lower the priority.

Where is your application exposed?

Your application is exposed when its code, or a library it uses, decompresses Brotli data an attacker controls, whether in a request body or in a response your service fetches. Vercel states that “Node.js does not decode Brotli data on its own”; something in your stack has to call the decoder. Three paths do:

PathWhen it appliesHow to find it
Request bodies via a body parserExpress 5.x depends on body-parser 2.x, which inflates “gzip, br (brotli), deflate and zstd encodings” with inflate defaulting to true. Express 4.x uses body-parser 1.x: gzip and deflate only, no Brotli path.npm ls express body-parser; check which parsers are mounted
Outbound fetch()Node’s built-in fetch (undici) auto-decodes br responses, so any fetch of a URL an attacker can influence, including image optimization and webhook callbacks, decompresses attacker-controlled data.Search for fetch( call sites that take user-supplied or third-party URLs
Direct node:zlib callsbrotliDecompress, brotliDecompressSync, createBrotliDecompress on input from outside your trust boundary`grep -rn “brotliDecompress\

Exposure paths. Sources: body-parser README (master, 2026-11-05); Express package.json and npm registry (2026-11-05); Bun advisory (2026-10-23); Vercel bulletin (2026-10-28).

Updating Express or body-parser changes nothing here. The decoder lives in the runtime, and body-parser 2.4.0 fixes a different CVE (CVE-2026-111181). The runtime release is the only fix.

The decoder hides in two more places. Bun 1.0.21 through 1.4.3 ships the same library; 1.4.4 moved to Brotli 1.2.1, and executables built with bun build –compile keep the old decoder until rebuilt, per the Bun advisory. Other languages are in scope too: GitHub advisories for the same CVE cover the PyPI brotli package, the .NET Brotli decoder, and a Perl binding (GitHub Advisory Database, 2026-11-05).

Next js vs Node js: does the flaw reach Next.js apps?

Yes, when the Node.js that builds or serves the Next.js app is an affected version. The “next js vs node js” framing confuses two layers: Next.js is a framework, and Node.js is the runtime it builds on and serves from, so a Next.js app inherits whichever Node.js runs it. Vercel patched its managed runtime for new deployments on October 28, 2026 and told Node.js 20 projects to move to 22.x or 24.x and redeploy. Self-hosted Next.js needs the same runtime upgrade as any Node.js service; Vercel notes that Next.js “does not block Brotli responses in image optimization,” which is the outbound fetch path from Table 3.

What’s the business impact?

An attacker who lands this exploit gets code execution inside the process that runs your application, with every secret, token, and network path that process holds. Even a failed attempt crashes the process, which on an internet-facing service means an outage. Retool’s disclosure lists the indicators it watched: SIGSEGV crashes, unexpected child processes, and outbound connections to the cloud metadata service. That last one turns one vulnerable service into a credential-theft event.

The reporting consequence depends on your facts, not on the CVE: assess notification duties under your contracts and regulations. Auditors and customers will ask the same three things: which environments were affected, when each was patched, and what proves it. Build that record as you go.

How to check Node.js version across servers, containers, CI, and laptops

Run node –version on every environment that runs Node.js and compare the output against 22.23.4, 24.22.1, and 26.12.1. Anything below those numbers in its line, and any end-of-life build, is vulnerable. A “check node js version” sweep is the first step of this response, and it covers far more than the production servers.

“`bash node –version

v24.22.2  <- patched

v24.20.0  <- vulnerable

v20.19.5  <- end of life, vulnerable at every patch level

“`

The same command works in Windows Command Prompt and PowerShell. Containers are where the inventory breaks: the runtime is baked into the image, so the host’s Node version tells you nothing. Query the image directly:

“`bash

What runtime does a given base image carry?

docker run –rm node:24.22.2-slim node –version

v24.22.2

Your own application image, by exact tag or digest

docker run –rm <registry>/<image>:<tag> node –version “`

Run it against every image in your registry, including the ones nobody has rebuilt in months. For CI runners, add a node –version step so every build records the runtime it used. For laptops, nvm ls or fnm list shows every installed version; an old default left in a shell profile is a common miss.

Aikido’s checker sends a crafted Brotli response to your process and crashes a vulnerable runtime, so run it only in a disposable process you’re authorized to test, and heed its caveat: “No output is not proof that your Node.js build is safe.” The version check is the proof.

stylized status table showing rows for environment, node version, owner, and verified with checkmarks on each row, gradient background. includes a footer line listing hosts and binaries.
a nodejs inventory is complete when every production host container image ci runner developer machine and compiled bun binary has a recorded verified runtime version

How to update Node.js to a fixed version

Move every install to the latest supported release in its line, through the channel that installed it, and finish every path with node –version. If you need to update Node.js across several package channels, remember that repositories can lag and floating tags can reuse cached images, so the verification line is part of the command.

Install channelCommandCaveat
nvmnvm install 24 && nvm use 24 && node –versionResolves to 24.22.2 on 2026-11-05; pin nvm install 24.22.2 in scripts and update .nvmrc.
fnmfnm install 24 && fnm use 24 && node –versionSame pinning advice as nvm.
Homebrew (macOS)brew update && brew upgrade node@24 && node –version (or node, node@22)Homebrew lists node 26.13.0, node@24 24.22.2, node@22 22.23.4 on 2026-11-05. Sysdig documented Homebrew lagging about 10 hours after release, so read the output.
Debian/Ubuntu via NodeSourceRefresh the NodeSource repository for your target major, reinstall nodejs, run node –versionFollow the current NodeSource instructions for your distribution rather than copying a stale setup command. Debian 12 and 13 ship a fixed system brotli for distro-packaged Node, per Sysdig.
Windows installer or package managerInstall the latest 22, 24, or 26 release from nodejs.org/download or your approved package channel, then run node –version in CMDPackage catalogs can trail nodejs.org by hours or days; verify the version rather than assuming the channel is current.
Docker base imagedocker pull node:24.22.2-slim, then rebuildSee the container section.
Bunbun upgrade && bun –versionNeeds 1.4.4 or newer; rebuild any bun build –compile executable.

How to update Node.js by install channel. Sources: Node.js dist index (2026-11-05); Homebrew formula page (2026-11-05); Bun advisory (2026-10-23); Sysdig (updated 2026-10-28). Distribution and package-manager instructions can change, so use their current official documentation and verify the installed version.

One rule applies to every row: a package manager can hand you an old version without complaint, so the node –version output is the result, not the exit code.

Containers and CI: rebuild, pull, pin

Rebuild and redeploy every image that carries its own Node.js, because patching the host does nothing for the runtime inside a container.

  1. Pull before you build. A floating tag such as node:24 resolves to whatever your builder cached. Sysdig’s write-up spells it out: a floating tag “stays on the old version if you rebuild from a cached image, so run docker pull first.”
  2. Pin exact tags. Change FROM node:24 to FROM node:24.22.2-slim, or to the image digest. The official image README notes that a tag with no version, such as node:slim, selects the Current release rather than an LTS line.
  3. Verify the artifact. docker run –rm <registry>/<image>:<tag> node –version on the pushed image is the evidence. Attach it to the ticket.

Then every CI pipeline must pull the rebuilt image, and every running workload must restart on it. A registry scan finds the pre-patch images your deployment list forgot. Test the rebuilt image in staging first, even under pressure.

Temporary controls while you upgrade (not a fix)

Temporary controls lower the odds that attacker-controlled Brotli reaches an unpatched decoder. They don’t fix the vulnerability, and each one should carry an expiry date tied to the upgrade ticket.

  • Block `Content-Encoding: br` at the edge. A WAF or reverse-proxy rule that rejects Brotli-encoded request bodies removes the inbound body-parser path. Vercel’s verdict on its own WAF rule applies to yours: it “reduces exposure but does not replace patching.”
  • Disable body inflation where you can. body-parser’s inflate: false rejects compressed bodies outright, per its README. That breaks clients that compress uploads, so check your API consumers first.
  • Accept that outbound traffic stays exposed. A WAF never sees the response your service fetches from a third-party or user-supplied URL. Datadog’s conclusion belongs in the ticket: “Only patching fixes this vulnerability.” Node.js has no per-request switch to skip decoding, so restrict which URLs unpatched services may fetch.
  • Watch for the indicators. SIGSEGV crashes, unexpected child processes, and outbound connections to the cloud metadata endpoint are the signals Retool listed. A spike in BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH errors on a patched build means someone is sending malformed streams at you.
LayerPlausible correctionEnterprise exposurePractical safeguard
Model providersConsolidation, price changes, reduced subsidies, tighter capacityAPI changes, model retirement, concentration riskAbstract model access, test substitutes, negotiate change notice
InfrastructureDelayed projects, higher power or capacity costs, regional constraintsPricing, latency, residency, resilience, deployment lead timeModel cost at several usage levels and retain regional options
Applications and vendorsFunding pressure, acquisition, product withdrawal, reduced supportWorkflow disruption, roadmap drift, lost integrationsRequire data export, dependency disclosure, and transition support
Enterprise deploymentsBudget scrutiny, paused expansion, tighter ROI requirementsStranded integration work or underused systemsUse bounded scope, KPI gates, monitoring, and rollback plans

How to verify remediation and monitor afterward

Remediation is verified when every environment in your inventory shows a fixed node –version output and the evidence is recorded against the ticket. A completed upgrade command isn’t proof; the version string on the running environment is. One trap: process.versions.brotli isn’t a patch indicator, because Node.js cherry-picked the upstream commit rather than bumping the bundled library version, per Sysdig.

After the sweep, run a vulnerability scanner across repositories, images, and running containers, and review application logs since October 21, 2026 for decompression errors, segfaults, or crash loops in Node processes.curity, procurement, or model-risk review in the relevant jurisdiction.

vertical stack of rounded white buttons labeled inventory, update, rebuild, and a black verify button against a soft gradient background.
remediation is finished when the inventory the upgrade and the image rebuild are followed by a recorded node version check on every environment

The upgrade trade-off: speed versus compatibility

An emergency runtime upgrade can break native modules, lockfile assumptions, and CI; delaying it leaves an exploited remote code execution flaw in production. Both risks are real, and the way through is to separate two kinds of upgrade.

A patch-level bump within the same major (24.20 to 24.22.2) carries little compatibility risk and should ship today, with a canary so a surprise shows up on one instance rather than all of them. A major-version migration (20 to 22 or 24) is a different project: native addons need rebuilding, deprecated APIs surface, and test suites find gaps. That migration is still mandatory for Node 20, but it deserves a scheduled plan with temporary controls covering the interval.

The uncomfortable half: a careful migration costs engineering weeks you didn’t plan to spend, and it’s the kind of work a modernization vendor would happily sell you. Patch within the line now, migrate on a plan, and let your dependency graph set the scope rather than the news cycle. The hidden costs of legacy systems include exactly this moment, when a runtime nobody owns has to move under deadline.

Ongoing Node.js security after this patch

Patching this CVE closes this CVE, and the next one is already scheduled: the Node.js project has pre-announced another HIGH-severity security release for 22.x, 24.x, and 26.x on or shortly after November 11, 2026. Plan to repeat this sweep next week.

For ongoing node js vulnerabilities, the nodejs.org vulnerability blog is the canonical feed, and CISA KEV tracks exploitation status. Add a Node.js version gate to CI so a build fails on an end-of-life or below-minimum runtime, pin versions and base images, and limit the untrusted input your services decompress.

The pattern isn’t unique to Node. PHP went through the same scramble in 2026, with the same lesson: runtime inventory comes first. Code written with AI assistants needs the same scrutiny, since generated scaffolding often pins nothing; the vibe coding security risks piece covers that side. The hardest cases sit inside legacy systems, where a Node 20 service can’t move because of a dependency nobody understands. That’s an application modernization decision rather than a patch.

When does an internal team need outside help?

Bring in outside help when the estate is larger than the people who can inventory it, when end-of-life majors need migration and nobody owns the runtime, or when the evidence trail has to satisfy an auditor while the team is on call for everything else. The decision is whether to hire node js developer capacity for the migration or to start with an audit that produces a prioritized risk register and a remediation plan estimated in engineering days. If you hire node js developer support, define the outcome as a verified runtime inventory and migration plan—not merely additional coding capacity. Teamvoy’s IT audit services page describes the audit route.

Node.js vulnerability response checklist

One sequence to work through:

Record the evidence, then repeat the sweep for the November 11, 2026 release.

Decide the target per line: latest supported release for 22, 24, and 26; migration target for 20 and older.

Inventory every environment that runs Node.js: servers, container images, CI runners, developer machines, Bun binaries, and non-Node services that embed Brotli.

Prioritize by exposure: Express 5 services with body parsers, anything that fetches user-influenced URLs, anything that decompresses untrusted input.

Apply temporary controls on anything that can’t upgrade today, each with an expiry date.

Update each environment to the latest release in its line; verify with node –version.

Rebuild and redeploy every container image and bun build –compile artifact; pull base images first; pin exact tags.

Verify and scan: version evidence per environment, registry scan for stragglers, log review since October 21, 2026.

Conclusion

CVE-2026-111497 is an exploited remote code execution flaw with a fix available since October 21, 2026, which makes the remaining risk an inventory problem rather than a patching problem. Find every runtime, including the ones inside images and on laptops, move each to the latest release in its line, rebuild what’s containerized, and keep the node –version evidence. Then do it again on November 11.

Talk to Teamvoy About Your Node.js Exposure

If your estate is bigger than the people who can inventory it, or a Node 20 service can’t move without a dependency nobody owns, an audit gives you the prioritized list and the engineering-day estimate before anyone touches production. Start with a technical assessment.

Frequently asked questions about CVE-2026-111497

Photo of Bohdan Varshchuk

, Chief Technology Officer

Bohdan brings over 15 years of experience in software development across Fintech, Blockchain, IoT, and Engineering Services. Passionate about innovation and digital transformation, he leads teams to deliver high-quality solutions that meet clients' unique needs. Bohdan is dedicated to helping businesses smooth operations, boost efficiency, and achieve sustainable growth.
 
Schedule a Call Connect on LinkedIn