Node.js released security patches today for all three of its active lines. That is 10 vulnerabilities, four of them high severity. If you have an API, a bot or a worker running on Node, it is worth setting aside some time this afternoon.
The fixed versions are 22.23.4, 24.22.1 and 26.12.1. You do not need to change lines: install the patch for the one you already use and you are done. If you are on a version that is out of support (25, 23, 20), no fix is coming for you and it is time to move to a maintained line.
What matters most
Four of the ten are high severity. Here is what each one does, without the fluff.
Brotli (CVE-2026-111497). An out-of-bounds write in the Brotli decoder, a compression format common in HTTP responses. The advisory says it could allow remote code execution and gives no more detail. The tricky part is that you do not have to use Brotli on purpose: fetch() decompresses responses with Content-Encoding: br on its own. An independent analysis that read undici's code concludes that asking for Accept-Encoding: identity does not protect you, because a malicious server can answer with Brotli anyway. That same analysis could not confirm the out-of-bounds write with the patch's test data, and I did not see a public exploit. Still, it is the one I would update for first.
TLS verification with odd IP addresses (CVE-2026-105483 and CVE-2026-106069). An IPv4 address can be written in many ways: 127.1, 0127.0.0.1, or with full-width digits. Node normalized those names and then compared them with the certificate's DNS names, so a certificate with something like 127.0.0.1 in its DNS list could pass as valid for those hosts. To take advantage of it, the attacker needs a certificate issued by a CA you trust, and the fix's own commit says it is not easy to exploit. It matters most for outgoing connections to hosts that come from outside, such as webhooks or URLs a user pastes in.
DNS and the NUL character (CVE-2026-105482). If you pass dns.resolve() a name with a \0 in the middle, the C library only reads what comes before it. In the fix's test, example.com\0.trusted.corp ends up querying example.com. It affects you if you validate names by suffix, for example "only domains ending in .mycompany.com".
The full list
| CVE | What it is | Severity | Lines |
|---|---|---|---|
| CVE-2026-105482 | dns.resolve truncates names containing a NUL character |
High | 22, 24, 26 |
| CVE-2026-105483 | TLS: full-width digits in an IP address | High | 24, 26 |
| CVE-2026-106069 | TLS: host that becomes an IP address after normalization | High | 22, 24, 26 |
| CVE-2026-111497 | Brotli: out-of-bounds write | High | 22, 24, 26 |
| CVE-2026-105481 | HTTP keep-alive: processes a response written before the request | Medium | 22, 24, 26 |
| CVE-2026-106072 | TLS: a non-canonical IPv4 is authenticated by a DNS name in the certificate | Medium | 22, 24, 26 |
| CVE-2026-106074 | randomUUID() and randomInt() repeat values when the process starts from a snapshot or SEA |
Medium | 22, 24, 26 |
| CVE-2026-106070 | ZipFile returns attacker-controlled bytes after rejecting a header | Low | 26 |
| CVE-2026-106071 | Permission Model: file permissions wider than intended with wildcards | Low | 26 |
| CVE-2026-106073 | Permission Model: check skipped with fs.realpathSync |
Low | 22, 24, 26 |
The two Permission Model ones only matter if you start Node with --permission. The randomUUID() one affects you if you ship apps packaged as a single executable (SEA) or with startup snapshots.
About eMudhra
This release also blocks certificate chains that go through eMudhra's compromised intermediate CAs, and updates the root certificates to NSS 3.131.1. If a connection starts failing with CERT_REVOKED after you update, that is expected behavior. Do not turn TLS verification off to hide it.
How to update
Start by checking which version you have:
bashnode -v
One catch: that command tells you which Node your terminal uses, not necessarily the one your service uses. If you run the app with systemd or PM2, it may be starting a different binary. The most reliable approach is to have the application log its version when it starts:
jsconsole.info('runtime-start', {
node: process.version,
execPath: process.execPath,
pid: process.pid
});
After deploying, look for that line in the logs of every replica and worker. That is how you find out if one of them stayed on the old Node.
With nvm:
bashnvm install 24
nvm use 24
With Docker or Dokploy: pin the version and rebuild. If you rebuild from an old cache you stay on the old version, so force a fresh image pull:
bashdocker build --pull --no-cache -t my-app:new .
docker run --rm my-app:new node -v
The official images node:24.22.1, node:22.23.4 and node:26.12.1 were already on Docker Hub shortly after the release. In Dokploy, do a redeploy with a rebuild.
With system packages (apt, NodeSource): check which version your repository offers before assuming it is patched. Some distributions fix things without changing the version number, so ask for the package's security advisory.
With binaries from nodejs.org: download the one for your line from the downloads page and verify the checksum before installing it.
And the most important part: installing is not enough. Restart your processes, because a Node that was already running keeps the old code until you restart it.
If you cannot update yet
There are two simple stopgaps. They do not replace the patch, but they help in the meantime.
For the NUL character, reject the name before resolving it:
jsif (name.includes('\0')) {
throw new Error('Invalid hostname');
}
For the odd IP addresses, reject hosts that are not an IP according to Node but turn into one when normalized (this check comes from the independent analysis I mentioned):
jsconst net = require('node:net');
const url = require('node:url');
const isNonCanonicalIP = (host) =>
!net.isIP(host) && net.isIP(url.domainToASCII(host)) !== 0;
Use it only with hosts that come from external input.
Quick questions
Does npm audit protect me? No. npm audit checks your project's dependencies, not the Node runtime. They are two separate updates.
Do I have to move to Node 26? No. Each line has its own patch: 22.23.4, 24.22.1 or 26.12.1. 26 is the Current line and the other two are LTS.
My version is out of support. Am I in danger? Node says that unsupported versions are always affected when a patch comes out, because they no longer get fixes. Plan the migration as soon as you can.
Does this mean I got hacked? No. An outdated version only tells you that you are missing the patch. It does not tell you whether someone got in. If you see strange processes or logins you do not recognize, keep your logs and investigate.
Sources
- Node.js advisory: https://nodejs.org/en/blog/vulnerability/october-2026-security-releases
- Release notes for 24.22.1: https://nodejs.org/en/blog/release/v24.22.1/
- Release notes for 22.23.4: https://nodejs.org/en/blog/release/v22.23.4/
- Release notes for 26.12.1: https://nodejs.org/en/blog/release/v26.12.1/
- Independent analysis by lilting: https://lilting.ch/en/articles/nodejs-tls-dns-brotli-security-release
- Teramont guide: https://teramont.net/es/blog/nodejs-vulnerabilidades-octubre-2026-actualizar-vps

ES
EN