Node.js October 2026 Security Updates
Node.js patched ten security issues on October 21, 2026, in versions 22.23.4, 24.22.1, and 26.12.1, including a high-severity Brotli decompression bug that can crash a server, leak memory, or lead to remote code execution.
This is for anyone running a Node.js app in production, in CI, or on a server they manage, even a small one. Below: what each fixed issue means in plain English, which release line it hits, and the exact steps to update, including Docker images. If you're also trying to figure out whether your whole site is exposed, not just Node.js itself, our guide on how to tell if your website is hackable is a good next read.
What happened
On October 21, 2026, the Node.js project shipped three security releases: v22.23.4, v24.22.1, and v26.12.1. Together they fix ten vulnerabilities and update five bundled dependencies. The project's own severity rating for the worst issue in this batch is "high," not critical, and it's still worth acting on even if nothing on your site looks broken. (Source: Node.js October 2026 Security Releases)
If you're running a version that's already End-of-Life (18.x, 20.x, or any line Node.js no longer maintains), the project's own policy treats EOL versions as automatically affected by every security release, since they never get patched again. If that's you, the fix isn't a patch version, it's moving to a supported line.
Which version am I actually running
Run this on the machine, or inside the container, that serves real traffic:
node -v
This matters more than it sounds. If your app runs in Docker, checking node -v on your laptop tells you nothing about what's inside the image. A container base image keeps whatever Node.js version was baked in at build time, no matter how patched the host OS is, until you actually rebuild it.
Am I affected
| Your Node.js major line | Status |
|---|---|
| 26.x, below 26.12.1 | Affected, update to 26.12.1 |
| 24.x, below 24.22.1 | Affected, update to 24.22.1 |
| 22.x, below 22.23.4 | Affected, update to 22.23.4 |
| Anything End-of-Life (18.x, 20.x, etc.) | Affected by policy, move to a supported line |
Being on an affected version is a reason to update, not proof that anyone has attacked you. Several of these bugs only matter if your app uses a specific feature, like Brotli decompression through node:zlib, or depends on a particular operating system's DNS resolver behavior. Still, one update covers all ten issues at once, which is simpler than deciding case by case whether each one applies to you.
High severity issues
These are the ones to prioritize first.
CVE-2026-111497, Brotli decoder out-of-bounds write (22.x, 24.x, 26.x). The Brotli decompression code bundled with Node.js can be made to write past the end of its internal buffer when fed malformed compressed data. If your app decompresses Brotli input with node:zlib (common when handling Content-Encoding: br on incoming requests or responses), an attacker who controls that compressed data could crash the process, read memory it shouldn't have access to, or in the worst case achieve remote code execution. It's the one most worth fixing quickly if your app decompresses any user-supplied Brotli data.
CVE-2026-105482, DNS NUL byte truncation (22.x, 24.x, 26.x). dns.resolve*() and dns.reverse() silently cut a hostname off at a NUL byte instead of rejecting it outright. If your app checks a hostname against an allowlist and then resolves it, an attacker can smuggle a NUL byte into the string so the check passes against one name while the actual DNS lookup resolves something else entirely. This is an incomplete fix of an earlier bug, CVE-2026-48930.
CVE-2026-106069, TLS verification fooled by a leading-zero IP (22.x, 24.x, 26.x). When a client connects to an address written like 0127.0.0.1, the WHATWG URL spec reads that as octal, but some operating systems, including macOS, read it as decimal. That mismatch could let TLS hostname verification check a server's certificate against the wrong IP address.
CVE-2026-105483, fullwidth-digit IPv4 bypass (24.x and 26.x only, not 22.x). tls.checkServerIdentity() failed to recognize an IPv4 address written with fullwidth Unicode digits as an actual IP address. That let a certificate with no matching IP SAN (the field in a certificate that lists which addresses it's valid for) still authenticate a connection to that address. This is a regression introduced after an earlier fix, CVE-2026-48618.
Medium severity issues
CVE-2026-106072, DNS-only certificate confused for an IP (22.x, 24.x, 26.x). A certificate that only has a DNS SAN, not an IP SAN, could still authenticate an IP connection if the client wrote the address in a non-standard form, such as 0177.0.0.1, 0x7f.0.0.1, 2130706433, or 127.1. Exploiting this needs two things lined up: a certificate with a numeric DNS SAN issued by a CA your system trusts, and a resolver that accepts these odd spellings, which glibc-based Linux systems do.
CVE-2026-105481, HTTP keep-alive response mix-up (22.x, 24.x, 26.x). Node's HTTP Agent can reuse a kept-alive connection and, under certain timing conditions, accept a response that was actually sent before the matching request went out. That can mean your code receives data meant for a different request. This is an incomplete fix of CVE-2026-48931.
CVE-2026-106074, predictable random values from snapshots (22.x, 24.x, 26.x). If you build a startup snapshot with --build-snapshot, or a single executable app using useSnapshot, the entropy cache behind crypto.randomUUID(), randomUUIDv7(), and randomInt() can get saved into that snapshot. Every process started from it then repeats the same values, up to 127 UUIDs and about 1,000 randomInt() results, until the cache refills. This only matters if you use Node's snapshot or single-executable-app build features; most typical web apps don't.
Low severity issues
CVE-2026-106070, ZipFile returns bad bytes after failed validation (26.x only). zlib.ZipFile could hand back attacker-controlled bytes after a ZIP header failed validation, instead of just failing cleanly.
CVE-2026-106071, Permission Model wildcard over-grant (26.x only). If you use Node's experimental Permission Model (the --permission flag) with wildcard filesystem rules, a lookup bug could grant broader filesystem access than you intended.
CVE-2026-106073, Permission Model bypass via realpathSync (22.x, 24.x, 26.x). fs.realpathSync() could be used to sidestep Permission Model filesystem restrictions. This is an incomplete fix of an earlier issue, CVE-2026-21715.
Dependency updates bundled in
Alongside the ten CVEs, these releases also pull in updated bundled dependencies:
- c-ares (22.x, 24.x, 26.x), the library Node.js uses for DNS resolution
- ca-cert (22.x, 24.x, 26.x), removing the compromised eMudhra intermediate CA from Node's trusted root store
- OpenSSL (22.x and 24.x)
- SQLite (22.x only)
- Undici (22.x, 24.x, 26.x), Node's built-in HTTP client
Even if none of the ten named CVEs apply to how you use Node, the eMudhra CA removal is worth having on its own: it stops your app from trusting certificates that chain up to a CA known to be compromised.
How to update
- Check your current version.
node -von the actual host, or inside the running container. - Pick the right target. Stay on your current major line: 22.x goes to 22.23.4, 24.x goes to 24.22.1, 26.x goes to 26.12.1.
- Using a version manager:
nvm install 22.23.4
nvm use 22.23.4
(swap in 24.22.1 or 26.12.1 for the other lines)
- Using official Docker images, bump the tag and rebuild the image, don't just restart the container:
FROM node:22.23.4-bookworm-slim
then
docker build --no-cache -t yourapp:latest .
docker compose up -d --build
Restarting a running container without rebuilding does nothing, because the old Node.js binary is already baked into that image layer.
- On a managed platform (a PaaS, a buildpack-based host), update the Node.js engine version in
package.jsonor the platform's version setting, then trigger a fresh build, not just a restart. - Confirm after deploy by running
node -vagain against the live, running process, not your local machine. - If you're on an End-of-Life major version, treat the upgrade to a supported line as its own project. A patch release won't exist for an EOL line.
If any of this sounds unfamiliar, or you're not even sure which of your production systems run Node.js, a manual security audit checks your actual running stack rather than just a version number in a config file.
Should I worry if my app doesn't do anything unusual
Most small business sites and typical web apps won't be hit by every issue on this list. The Brotli bug matters most if your app decompresses user-controlled data. The TLS and DNS issues matter most if you make outbound HTTPS requests to addresses you don't fully control, or if you lean on hostname allowlisting as a security boundary. The Permission Model bugs only matter if you've opted into Node's experimental permission flags. Still, since the fixes ship together in one release, updating once covers all of them, which is simpler than auditing each CVE against your own code.
If you want a quick outside read on your current exposure, our free website security check and security headers tool will show you what an attacker can already see about your stack without you lifting a finger.
Key takeaways
- Update to Node.js v22.23.4, v24.22.1, or v26.12.1 depending on your major line. The highest severity fixed in this batch is high, not critical.
- Check the version inside your actual running container with
node -v, and rebuild Docker images rather than restarting them; old images keep the old Node.js binary. - Prioritize the Brotli decoder bug (CVE-2026-111497) if your app decompresses Brotli data through
node:zlib. - The TLS and DNS fixes mostly matter for apps doing hostname allowlisting or making outbound requests to addresses they don't fully control.
- If you're on an End-of-Life Node.js version, the project treats you as affected by default, since EOL lines never get another patch.
Patching Node.js closes the specific holes in this release, but it won't catch everything else that could be wrong on your site, like an exposed admin panel or weak session handling. That's the gap a manual audit is built for: a real person checks your actual site, not just your dependency versions, for $49.
A real human security engineer audits your whole site by hand and sends a full report: every issue, its severity, and the exact fix. From $49, with a 14-day money-back guarantee.
See pricing