Quick answer
CVE-2026-42533 is a heap buffer overflow in nginx's map module. When a map uses a regex and a string expression references the map's capture variables before the map output, or uses a self-dependent volatile map, the length and copy passes of nginx's script engine disagree and the worker writes past the allocation. It affects nginx 0.9.6 to 1.31.2 and is fixed in 1.31.3 and 1.30.4. A companion slice-module issue, CVE-2026-60005, was fixed in the same releases.
At a glance
critical severity- Identifier
- CVE-2026-42533
- Product
- nginx (open source and NGINX Plus)
- Affected
- nginx open source 0.9.6 – 1.31.2; NGINX Plus releases built on those versions
- Fixed in
- nginx 1.31.3 (mainline); nginx 1.30.4 (stable); NGINX Plus R36 P7, PLS.37.0.3.1
- CVSS
- 8.1 (CVSS 3.1) / 9.2 (CVSS 4.0), per F5; 7.0 per Red Hat
- Disclosed
- Known exploited (CISA KEV)
- Not listed
Patched July 2026. Requires a non-default map/regex configuration. No in-the-wild exploitation reported; not in CISA KEV as of 24 October 2026.
01What is CVE-2026-42533?
CVE-2026-42533 is a heap buffer overflow in nginx's map module, and in the equivalent module in the stream subsystem. An unauthenticated attacker sends a crafted request, the worker process writes attacker-controlled bytes past a heap allocation, and the worker crashes and restarts. As with the related rewrite bug, the vendor describes code execution as possible where ASLR is disabled or bypassed; the dependable outcome is denial of service.
The nginx changelog credits Mufeed VH of Winfunc Research and Maxim Dounin, and the issue was disclosed on 15 July 2026. The affected code reaches back to nginx 0.9.6 (March 2011), when regex support was added to the map directive, so it spans fifteen years of releases.
Like the NGINX Rift rewrite overflow, this is a data-plane bug in nginx's script engine. The root cause is the same family of problem: the engine measures a buffer in one pass and fills it in another, and an attacker can make the two passes disagree.
02How does the map overflow happen?
nginx builds string values such as log lines, document roots and proxied headers using a two-pass script engine. The length pass totals the bytes needed and allocates exactly that; the copy pass writes the data. Both passes read the request's regex capture state, which is shared and mutable.
The bug appears when a single string expression references a positional capture such as $1 and then evaluates a regex-backed map. During the length pass, $1 may be empty, so it reserves little or no space. Evaluating the map then runs its own regex over attacker-controlled input and overwrites the shared capture array with a new, larger value. The copy pass revisits $1, now finds the new long capture, and copies it into the buffer that was sized for the old short one. The surplus overflows the allocation.
A second route reaches the same sink: a non-cacheable map marked volatile that depends on its own capture. Because its value can change between the length and copy passes, the two passes again disagree on size. Winfunc's write-up confirmed the overflow on a stream listener using ssl_preread, where the attacker-controlled TLS SNI hostname was copied into a one-byte allocation.
03Who is affected?
Open source nginx 0.9.6 through 1.31.2 is listed as vulnerable, along with NGINX Plus releases built on those versions. Exposure requires the specific configuration shape, so a version match alone does not mean you are exploitable.
The vulnerable shapes come straight from the upstream fix commit. The first is a string expression that reads a capture before a regex map; the second is a self-dependent volatile map.
# A: capture read before the regex map output
map $uri $m {
~(?<capture>.*) $capture;
}
set $capture "";
set $temp "$capture $m"; # $capture measured, then $m clobbers it
# B: self-dependent volatile map
map prefix:$capture $m_volatile {
volatile;
~(?<capture>.*) $capture;
}
set $capture "";
set $temp "$m_volatile";04How do I audit my configuration?
Dump the merged configuration and look for two things: regex maps with captures, and volatile maps. Then confirm, by reading the surrounding blocks, whether a captured variable is used outside its own map block or before the map output in the same expression.
nginx -T 2>/dev/null > /tmp/nginx-full.conf
# map blocks and regex entries that define a named capture
grep -nE '^\s*map\s|^\s*~\*?\S*\(' /tmp/nginx-full.conf
# volatile maps (the self-dependent variant)
grep -nE '^\s*volatile\s*;' /tmp/nginx-full.conf
# for each captured name, see where it is used outside its map
for c in $(grep -E '^\s*~' /tmp/nginx-full.conf \
| grep -oE '\?<[A-Za-z_][A-Za-z0-9_]*>' | tr -d '?<>' | sort -u); do
echo "== \$$c"; grep -nE "\\$\{?$c\b" /tmp/nginx-full.conf
done05How is it fixed?
Upgrade to nginx 1.31.3 (mainline) or 1.30.4 (stable); NGINX Plus users should move to R36 P7 or PLS.37.0.3.1 (LTS), both released on 15 July 2026. The fix records the end of the allocated buffer and routes every literal, variable and capture copy through a shared length guard. If a copy would exceed the buffer, nginx now logs "no buffer space in script copy", aborts the script and returns an internal error instead of writing out of bounds — it fails closed.
Distribution packages carry it too: Debian shipped it in nginx 1.26.3-3+deb13u8 for trixie (DSA-6496-1) and in 1.22.1-9+deb12u10 for bookworm through Debian LTS (DLA-4784-1). Match the package version your distribution publishes.
If you cannot upgrade at once, remove the trigger. Do not use unnamed captures in these expressions; use a uniquely named capture and reference it only inside the same block as the regex match. Reorder expressions so a map output is not preceded by a capture reference it depends on.
- Primary fix: upgrade to nginx 1.31.3 / 1.30.4, or the matching distro package
- Config mitigation: name captures and use them only inside their own map block
- Avoid self-referential volatile maps built from their own capture
- Restart nginx so workers reload the patched binary
07What can an edge proxy actually do here?
The honest answer mirrors the rewrite bug. CVE-2026-42533 executes inside the nginx worker that processes the request, so a filter inside that same vulnerable nginx cannot be relied on to stop it. The stream variant is worse for edge filtering, because it is driven by the TLS SNI during the handshake — before any HTTP-layer inspection runs. Understanding where TLS sits helps here: see what SSL/TLS is.
A separate, patched tier in front of an origin reduces exposure and absorbs the crash-loop denial of service, in the same way any reverse proxy shields an origin. It cannot make an unpatched nginx safe, which is the general limit of any virtual patch. Patch first; use edge protection to limit blast radius and to soak up flooding. For what that layer does more broadly, see what a WAF is.
Questions
Frequently asked questions
Sources
Sources and verification
Both map patterns from the fix commit loaded into nginx 1.22.1 with nginx -t, and the audit greps and loop run with GNU grep 3.8 against a test configuration, on Debian 12, October 2026.
- 01NVD — CVE-2026-42533 · NVD
- 02nginx security advisories · nginx.org
- 03F5 advisory K000162097 · F5
- 04Winfunc Research — CVE-2026-42533 disclosure record · Winfunc Research
- 05nginx fix commit b767540 (script buffer overrun protection) · nginx GitHub
- 06F5 advisory K000162100 (CVE-2026-60005, slice module) · F5
- 07Debian security tracker — CVE-2026-42533 · Debian
- 08Red Hat — CVE-2026-42533 · Red Hat
- 09NGINX Plus release notes · F5 NGINX docs
- 10nginx changelog (CHANGES) · nginx.org
Last updated