Skip to content
chornous.dev

Type two or more letters. Esc closes.

Index of sheets
Theme

Sheet 03 · Writing

All notes

Node.js 22.23.4, 24.22.1 and 26.12.1: a Brotli out-of-bounds write, three TLS hostname bypasses and repeated random UUIDs

The Node.js project shipped security releases for 22.x, 24.x and 26.x on October 21, 2026. They fix ten CVEs, four rated high, including an out-of-bounds write in the bundled Brotli decoder (CVE-2026-111497) and TLS hostname checks that non-canonical IPv4 spellings could fool.

Pl. 65 · pipeline drawing generated from the slug “nodejs-october-2026-security-brotli-tls”

The Node.js project published security releases on October 21, 2026: v22.23.4, v24.22.1 and v26.12.1. They fix ten CVEs across the three supported lines. Four rate high. The same releases update c-ares and Undici on all three lines, OpenSSL on 22.x and 24.x, SQLite on 22.x, and the bundled CA certificates in response to the eMudhra intermediate CA compromise.

The high-severity four

High-severity CVEs in the October 21, 2026 Node.js releases
CVEAreaBugLines
CVE-2026-111497node:zlibBrotli decoder writes past an 8-byte buffer22, 24, 26
CVE-2026-105482dnsdns.resolve*() and dns.reverse() truncate names at a NUL byte22, 24, 26
CVE-2026-106069tlsleading-zero IPv4 hosts get checked against a different address22, 24, 26
CVE-2026-105483tlsfullwidth digits in an IPv4 host skip the IP SAN check24, 26

Brotli: CVE-2026-111497

The Brotli decoder bundled with Node.js treated an invalid block switch as a request for more input instead of a format error. The streaming decoder kept appending bytes to an eight-byte internal buffer and ran past its end. Anyone who can hand your process Brotli data that you decompress with node:zlib can corrupt memory. The advisory lists a crash, disclosure of process memory, or remote code execution as outcomes.

The pattern to look for in your code:

import zlib from "node:zlib";

// Decompressing uploads or webhook bodies that arrive as br
app.post("/ingest", (req, res) => {
  if (req.headers["content-encoding"] === "br") {
    req.pipe(zlib.createBrotliDecompress()).pipe(sink);
  }
});

A body-parsing middleware that inflates Content-Encoding: br requests through node:zlib puts you in the same spot, even if your own code never names Brotli. Researchers from OpenAI's Codex Security team reported the bug, and Node.js core maintainers mcollina and aduh95 wrote the fix.

TLS and DNS

Three of the bugs let a hostname string say one thing to the certificate check and another to the resolver.

  • CVE-2026-106069. tls.checkServerIdentity() follows WHATWG URL rules, so it reads 0127.0.0.1 as octal and checks the certificate against 87.0.0.1. The macOS resolver reads the same string as decimal and connects to 127.0.0.1.
  • CVE-2026-105483. A host written with fullwidth digits, such as 127.0.0.1, connects to an IPv4 address without a matching IP SAN in the certificate. The project calls it a regression from the fix for CVE-2026-48618, and it affects 24.x and 26.x.
  • CVE-2026-105482. dns.resolve*() passes the name to c-ares as a C string, so attacker.example\0.trusted.example resolves attacker.example and returns no error. An earlier fix covered dns.lookup() and missed these functions.

A medium-rated sibling, CVE-2026-106072, lets a certificate with a numeric DNS SAN authenticate an IP endpoint when the client uses spellings such as 0x7f.0.0.1 or 127.1 on a resolver that accepts them, glibc among them.

All four matter most when your server connects to hosts that users choose: webhooks, link previews, SSRF filters that validate a hostname before a request.

Snapshots and single executables

CVE-2026-106074, rated medium, hits a narrower group. If you build a startup snapshot with --build-snapshot or a single executable application with useSnapshot, Node.js saved the entropy caches for crypto.randomUUID(), crypto.randomUUIDv7() and crypto.randomInt() into the snapshot. Every process started from it returned the same values until the cache refilled: up to 127 UUIDs and about 1,000 randomInt() results.

If you ship a SEA or snapshot, rebuild it on the patched Node.js. Then look for IDs minted near process start that collided across instances.

The rest

Medium and low CVEs, October 21, 2026
CVESeveritySummary
CVE-2026-105481MediumHTTP Agent keep-alive socket accepts a response sent before the request
CVE-2026-106070Lowzlib.ZipFile returns attacker bytes after failed header checks (26.x)
CVE-2026-106071Low--allow-fs-read=/etc/passwd.* also grants /etc/passwd (26.x)
CVE-2026-106073Lowfs.realpathSync() skips Permission Model read checks

Upgrade

node -v

# nvm
nvm install 24.22.1 && nvm alias default 24.22.1

# Docker: pin the patched version in your FROM line, then rebuild
docker build --pull -t my-service .

The advisory reminds you that end-of-life versions get no fixes and count as affected. If a service still runs a line outside 22, 24 and 26, these CVEs stay open on it.

This week

  1. Move every service to 22.23.4, 24.22.1 or 26.12.1. Start with services that decompress request bodies or connect to hosts your users pick.
  2. Grep for createBrotliDecompress, brotliDecompress and body parsers with br enabled, so you know where CVE-2026-111497 reached you.
  3. Rebuild any single executable application or startup snapshot.
  4. If you validate hosts in an SSRF filter, test it with 0127.0.0.1, 0x7f.0.0.1, 127.1 and fullwidth digits after the upgrade.

Volodymyr Chornous