What the October 2026 Node.js release fixes
On 21 October 2026, Node.js published updates for the 22.x, 24.x and 26.x lines. Among the ten vulnerabilities fixed, the project rates CVE-2026-111497 as High: the bundled Brotli decoder writes past an internal buffer when it receives malformed data. Concretely, an invalid block switch was reported as a mere need for more input rather than a permanent format error. The streaming decoder then kept appending bytes to an eight-byte internal buffer. The possible consequences range from a process crash to memory disclosure and remote code execution with the privileges of the Node process.
On severity, two readings coexist. Node.js says High; Google, as CVE numbering authority, assigns a CVSS v4 score of 9.2, according to Rapid7's analysis. As of 26 October 2026, Rapid7 is not aware of any exploitation in the wild, and the flaw is not in the CISA Known Exploited Vulnerabilities catalog. The flaw is therefore not exploited so far, according to Rapid7: this is a window to patch calmly, not a reason to wait.
Affected versions and fixed versions
Scroll the table
| Case | Status | Action |
|---|---|---|
| Node.js 22.x | Affected before 22.23.4 | Move to 22.23.4 |
| Node.js 24.x | Affected before 24.22.1 | Move to 24.22.1 |
| Node.js 26.x | Affected before 26.12.1 | Move to 26.12.1 |
| Node.js 20.x and other end-of-life lines | Treat as affected, no fix available | Migrate to 22.x or 24.x |
| Docker image node:<line> | Affected until the image is rebuilt | Rebuild with --pull --no-cache |
| Node binary bundled in a tool (Electron, packaged executable) | Depends on the embedded version | Update the tool itself |
| Other software that embeds the same Brotli decoder | Depends on the vendor | Read its own advisory |
Are you exposed: the deciding criterion
Running a vulnerable Node is not enough to be attackable. The Node.js advisory targets an application that decompresses attacker-supplied Brotli data with node:zlib, through zlib.createBrotliDecompress or zlib.brotliDecompress. Rapid7 points out that the mere presence of the decoder does not establish exposure: everything depends on what the application decompresses. Do not conclude too quickly that there is no risk, though, because Brotli often goes through libraries you did not write.
The link with the Content-Encoding: br header is our reading, not a statement from the advisory. In the public source code, the fetch built into Node (undici) decodes br responses with zlib.createBrotliDecompress, the axios HTTP adapter provides the same decoding, and the current body-parser code does the same for incoming request bodies. Two flows therefore need review: what your application receives from clients, and what it fetches from third-party servers. You can check this in your own dependency tree, with the inventory commands below.
Where untrusted Brotli can enter a Node application
- Compressed incoming requests — an Express API or a custom server that uses body-parser decompresses a
Content-Encoding: brbody sent by any client. - Responses from third-party services —
fetchor axios calling an API, an RSS feed, a webhook or a page to preview: the remote server chooses the encoding of the response. - Server-side rendering — a Next or Nuxt application that fetches remote data during rendering goes through those same outgoing calls.
- Proxies and gateways written in Node — a component that decompresses to inspect or transform content in transit opens both flows at once.
- File processing — a service that accepts Brotli-compressed files or archives and opens them with
zlib.brotliDecompress. - Build and CI tooling — deployment scripts and jobs that download artifacts: less exposed, but they use the same binary and get patched at the same time.
- No path identified — lower priority, not zero: a dependency added later is enough to create exposure, and the release also fixes other flaws.
Inventory your fleet in fifteen minutes
Read the version on each machine
node -vwhich -a node
Several binaries often coexist: the system one, the nvm one, one inside a container.which -alists them all, and the first is not always the one the service uses.Find the real binary of each process
ps -eo pid,user,args | grep -E '[n]ode|[p]m2'sudo readlink -f /proc/<pid>/exe
The second command, run with the PID you found, gives the exact path of the binary running the process. It is the only reliable answer on a machine that carries several Node installations.Query the containers
docker psdocker exec <conteneur> node -vdocker images | grep node
A running container does not fix itself: it keeps the image it started with, even if a newer image exists on the machine.Search your code for direct calls
grep -rEn "createBrotliDecompress|brotliDecompress" --include=*.js --include=*.mjs --include=*.ts . --exclude-dir=node_modules
Each line found is a point where your code decompresses Brotli. Look at where the data comes from: a file you produced yourself carries a different risk than a request body.Search for libraries that decompress on your behalf
grep -rlE "createBrotliDecompress" node_modules --include=*.jsnpm ls body-parser axios undici
The first command lists installed packages that call the decoder; the second shows which versions of body-parser, axios and undici are present in the project. Run them in every repository, not only the most recent one.Spot bundled binaries
Tools that ship their own Node (Electron applications, packaged executables) are not covered by
apt. Look up their version in their documentation and check whether the vendor has released a fixed version.Record the result in a table
One row per process: machine, client, Node line, version, Brotli path identified or not. This table decides the order of work, and it will serve as proof once the update is done.
In which order to handle the fleet
A fleet of client sites with mixed versions and installations cannot be updated in one move, and it does not need to be. Start with the Internet-facing servers that receive compressed bodies or call third-party services: server-side rendering, gateways, proxies, public APIs. Internal applications and workers come next, then build tooling. Applications on Node 20 are a separate case: no fix will ever exist for them, and the only way out is migrating to 22.x or 24.x, which is better planned with the client than improvised. Work in stages of a few machines, and verify each stage before moving to the next.
Update according to the installation method
apt package (NodeSource repository or distribution)
apt-cache policy nodejssudo apt-get updatesudo apt-get install --only-upgrade nodejsnode -v
First read the source displayed byapt-cache policy: the repository must point to the right line (node_22.x or node_24.x). A repository left on an end-of-life line will never offer the fix. A distribution package may also carry a different number: compare with your distribution's advisory.nvm
nvm install --reinstall-packages-from=current 22nvm alias default 22nvm use 22node -v
The command installs the latest 22.x available; check thatnode -vshows 22.23.4 or higher. Do the same with 24 if that is your line. Services started by another user have their own nvm.Docker
Change the tag on the
FROMline, for exampleFROM node:22orFROM node:24with the variant you already use, then:docker build --pull --no-cache -t monapp:corrige .docker compose up -d
The--pulloption fetches the latest base image,--no-cacheavoids reusing a layer built with the old Node. The running container is only replaced at redeployment.pm2
pm2 restart allpm2 update
After the binary is replaced,pm2 restartrelaunches the applications;pm2 updaterefreshes the pm2 daemon in memory. The pm2 documentation adds that after a Node upgrade you should also refresh the startup script:pm2 unstartuppm2 startuppm2 savesystemd service or another supervisor
sudo systemctl restart <service>
Restart each service one at a time, checking its log and health route before moving to the next. For an application behind a load balancer, take the machine out of the pool during the restart.
A process already running keeps the old Node
Replacing the binary does not fix running processes: they keep the old version in memory until they restart. A correct node -v on the machine therefore proves nothing about a service started yesterday. After each restart, verify from the process itself: pm2 jlist or pm2 show <nom> for the Node version in use, or process.version exposed in your health route.
If updating is impossible today
Node.js has published no workaround: the only vendor mitigation is the fixed version. Failing that, Rapid7 recommends restricting or disabling the application paths that decompress untrusted Brotli. Here is what that looks like in practice. The following points are risk-reduction measures we suggest, not vendor recommendations, and none replaces the fix.
On incoming requests, refuse Brotli at the reverse proxy level, for example in nginx: if ($http_content_encoding ~* br) { return 415; }. Test with nginx -t before reloading, and check that none of your legitimate clients sends br bodies. For responses from third parties, advertise only the useful encodings with the Accept-Encoding: gzip header, and limit the destinations your outgoing calls may reach. That last measure is partial: a malicious server can answer with br even if it was not requested, and the decoder follows the response header. On Vercel, WAF rules block the inbound flow but not the responses your functions fetch; redeploying with a fixed version is still necessary.
Do not fix only the Brotli flaw
The same release fixes nine other flaws. They include two high-severity TLS hostname verification bypasses, CVE-2026-105483 and CVE-2026-106069, as well as CVE-2026-105482, a truncation of hostnames containing a NUL character in DNS resolution, also rated High. They do not all affect the same lines: CVE-2026-105483 concerns the 26.x and 24.x lines, while the other two also concern 22.x. An application that validates TLS certificates for its outgoing calls therefore has good reasons to move to the fixed version without waiting to settle the Brotli question.
For an agency: one fix per line, not per site
When you carry dozens of sites, the update command takes a minute; the time goes elsewhere. You have to find which machine runs which version for which client, then obtain a restart window. Keep a living register, fed by the inventory above: at the next flaw, a simple filter on the Node line gives the list of sites to handle. The fewer variants in the fleet, the fewer cases to handle by hand, and reseller hosting follows that logic: a single interface for the portfolio and grouped renewals, whereas a collection of disparate servers multiplies the accesses to track. Applications stuck on Node 20 need separate handling: the migration guide linked below this article spares you from discovering the absence of a fix on the day of the next flaw.
The official documentation
Node.js security advisory of October 2026: https://nodejs.org/en/blog/vulnerability/october-2026-security-releases
Rapid7 analysis of CVE-2026-111497: https://www.rapid7.com/blog/post/etr-cve-2026-111497-critical-out-of-bounds-write-in-the-node-js-brotli-decoder/
Vercel bulletin: https://vercel.com/kb/bulletin/node-js-security-advisory
zlib module documentation: https://nodejs.org/api/zlib.html
nvm documentation: https://github.com/nvm-sh/nvm
Updating pm2: https://pm2.keymetrics.io/docs/usage/update-pm2/
docker build options: https://docs.docker.com/reference/cli/docker/buildx/build/