psf-node-oct2026-mitigate(8)
Node.js October 2026 mitigation (v1)
CVE-2026-111497 (Brotli decoder out-of-bounds write, RCE) and the nine other
CVEs fixed in Node.js 22.23.4 / 24.22.1 / 26.12.1 on 21 Oct 2026
If this software is helpful, consider a donation to our 501c3 nonprofit:
https://privacysafe.foundation
Usage:
./node-oct2026-mitigate.sh [command] [--unit NAME]... [--force]
check (default) read-only report: every Node runtime on the host (PATH,
nvm, n, fnm, volta, asdf, /opt, running processes,
container images), whether each is fixed, which running
processes still need a restart or a guard. Root optional
(root sees every process). Exit 0 = nothing exposed,
1 = unfixed runtime in use, 2 = something couldn't be read.
scan read-only: find application code and dependencies that
decode Brotli, Node single executable applications (SEAs)
and startup snapshots that must be rebuilt
(CVE-2026-106074). Exit 0 = none, 1 = findings.
guard --unit U load brotli-guard.cjs into systemd unit U through a
drop-in that adds --require to NODE_OPTIONS, restart it,
and prove the guard is live. Rolls back if U won't start.
unguard --unit U remove that drop-in and restart U.
status guarded units, their runtime, and what the guard blocked.
hunt read-only: scan the journal and logs for Node crashes
(segfaults, V8 fatal errors, Brotli decoder frames) and
guard events. Exit 0 = clean, 1 = findings.
--unit NAME systemd unit for guard/unguard (repeatable; .service
is added if missing)
--force guard: install even if the guard's self-test fails on
the unit's runtime, or the runtime is already fixed
This script never executes a Node binary as root unless root owns it and
nobody else can write it. Versions are read from the binary's contents, so
a binary planted in a user's ~/.nvm or inside a container is never run with
root's privileges.
Env overrides:
NODE_FIXED_22=22.23.4 NODE_FIXED_24=24.22.1 NODE_FIXED_26=26.12.1
first fixed release per line
FIXED_BUILDS="20.19.2+dfsg-1+deb13u2" distro builds known to carry the
fix (Debian/Ubuntu backport to an
upstream-EOL line)
SCAN_PATHS="/srv /opt /var/www /home /usr/local/lib /usr/lib/node_modules"
SCAN_DEPTH=8 how deep scan descends
GUARD_DST=/usr/local/lib/privacysafe/brotli-guard.cjs
HUNT_SINCE="2026-10-14" how far back hunt reads the journal
GUARD_SRC=./brotli-guard.cjs the guard file to install (default: the copy
next to this script)
PSF_LOCK_WAIT seconds a run that changes the host waits for another one that is already
changing it (default 30), then stops with exit 2; the lock is STATE_DIR/.lockThe Security Patches software and this documentation are dedicated to the public domain under CC0 1.0 Universal. Other pages on privacysafe.app/docs are CC BY-SA 4.0 unless the page says otherwise.