psf-nginx-oct2026-check(8)
nginx October 2026 security release: checker with optional workarounds (v1)
CVE-2026-15176 CVE-2026-93479 CVE-2026-97205 CVE-2026-95101 CVE-2026-97629
njs: CVE-2026-101019 CVE-2026-101025
If this software is helpful, consider a donation to our 501c3 nonprofit:
https://privacysafe.foundation
nginx 1.30.6 (stable) and 1.31.7 (mainline), 14 October 2026, fix five flaws.
Three are heap/use-after-free memory bugs in worker processes (a crash, and
possibly code execution): CVE-2026-15176 (alias with a rewrite),
CVE-2026-93479 (a regex map's captures used by root or log_format), and
CVE-2026-97205 (AIO with SSI). One forges a TLS session that can bypass
client-certificate checks (CVE-2026-97629, automatic session-ticket-key
rotation). One slips extra bytes into a proxied request (CVE-2026-95101,
HTTP/3). nginx rates all five medium; F5 scores the three memory bugs 9.2
critical, the TLS flaw 8.3, the HTTP/3 flaw 6.9. None was reported exploited
as of mid-October 2026. njs 1.0.2 separately fixes two XML-module flaws in
the JavaScript module (CVE-2026-101019, CVE-2026-101025).
Each flaw needs a specific directive in your configuration, so a vulnerable
nginx version is not necessarily reachable. "check" and "hunt" are read-only: "check"
reports the nginx and njs versions on the host (and in containers), and audits the
running configuration (nginx -T) for the directive combination each flaw
needs, with F5's workaround for the ones you are exposed to; it
changes nothing. CVE-2026-42533, a critical script engine overflow fixed on 15 July in
1.30.4 / 1.31.3, is not audited by name: this tool's version bar is newer, so an nginx that
passes "check" has that fix. A downstream distribution reported on 4 November that the Red
Hat family backport of that fix makes nginx answer a share of requests with HTTP 500 when a
set or rewrite uses a variable from a map marked volatile; "check" prints an information
line (no exit code change) when the running configuration has such a map on a Red Hat
family host. The fix is to upgrade to 1.30.6 / 1.31.7 (or your distro's
backport) and reload. "mitigate" is the only command that edits nginx.conf, and only
for the three simple workarounds you choose, with a copy of every file and an
automatic undo if nginx rejects the result; the others need an administrator.
Usage:
./nginx-oct2026-check.sh [command]
check (default) nginx and njs versions on the host and in containers, and
a configuration audit of the running nginx for the five
flaws' trigger directives. Root optional, but nginx -T
usually needs root to read the full config. Exit 0 =
nothing exposed, 1 = a vulnerable nginx/njs is present,
2 = something couldn't be read.
mitigate [options] (root) changes the host. Applies F5's own workarounds for
the flaws your running configuration is exposed to (the same audit as
check, so a patched build or an unexposed flaw is left alone). You must
choose among these; with no option it applies --tickets-off and --aio-off,
the two low-impact measures. Options:
--tickets-off CVE-2026-97629: where ssl_session_cache is
shared, adds ssl_session_tickets off (TLS
session resumption through the shared cache
still works; ticket resumption stops)
--aio-off CVE-2026-97205: replaces "aio on" and "aio
threads" with "aio off" (slower file serving
under load; nothing breaks)
--proxy-buffering-off CVE-2026-95101: sets proxy_request_buffering
off at the http level (request bodies are
streamed to the upstream: retries stop, and
an upstream that needs Content-Length may
fail), only when the config sets it nowhere
--force apply a chosen measure even if the audit does
not report that flaw as exposed
--dry-run, --reload show only; graceful reload afterwards
Every file is copied first and checked with nginx -t before and after;
if nginx rejects the result the originals are put back at once. Not
automated, because they need a person to read the configuration:
CVE-2026-15176 (alias with a rewrite and $request_filename) and
CVE-2026-93479 (a regex map whose captures feed root or log_format).
These are F5's workarounds; the permanent fix is to upgrade.
rollback [--dry-run] [--reload] put back every file mitigate changed.
hunt read-only: the journal and logs for nginx worker crashes
(segfaults, aborts), the likely symptom of the memory
bugs. Exit 0 = clean, 1 = findings.
version print the script version.
Env overrides:
FIXED_BUILDS="1.30.1-1~deb13u2" distro nginx builds known to carry the
backported fix, space-separated full
versions (checked for dpkg-owned nginx)
NGINX_STABLE_FIXED=1.30.6 first fixed stable release
NGINX_MAINLINE_FIXED=1.31.7 first fixed mainline release
NJS_FIXED=1.0.2 first fixed njs release
SCAN_CONTAINERS=1 1 = read nginx inside running containers
STATE_DIR (default /var/lib/psf-security-patches/nginx) holds the backups and manifest
NGINX_BIN, NGINX_MAIN_CONF, NGINX_CONF_FILES for mitigate: the binary, a non-default
main configuration file, and the files to edit
NGINX_T=1 1 = run "nginx -T" for the config audit
(0 to skip it)
OS_RELEASE=/etc/os-release names the distribution; check prints a note about a reported
regression only on a Red Hat family host (see below)
HUNT_SINCE="2026-10-01" how far back hunt reads the journal
HUNT_LOGS="/var/log/nginx/*.log" extra log globs for hunt
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.