Skip to main content

CVE-2026-42533: The 15-Year-Old Core-NGINX Heap Overflow Your Gateway API Migration Didn't Escape

10 min readDora NodaDora Noda
Share
On this page

You did the responsible thing. When the Kubernetes project archived ingress-nginx in March, you migrated your edge to Gateway API — maybe to F5's NGINX Gateway Fabric, maybe to F5's NGINX Ingress Controller — and closed the book on the dead controller's annotation-injection CVEs. On July 15, 2026, F5 disclosed a CVSS 9.2 heap buffer overflow that lives one layer deeper: in core NGINX itself, in code that has shipped in every release since March 2011. If the Gateway API implementation underneath your new edge is NGINX-based, the migration moved you from one vulnerable NGINX to another.

That is the uncomfortable shape of CVE-2026-42533. It is not a bug in the retired community controller. It is a bug in the map directive's regex handling in NGINX Open Source and NGINX Plus — the same request-terminating engine that powers F5's Gateway Fabric, Ingress Controller, App Protect WAF, and Instance Manager. One crafted HTTP request from an unauthenticated attacker can crash a worker process, and under the wrong conditions it can do worse. Here is the full patch matrix, the exact config that makes you exploitable, and the order to fix things in.

The patch matrix: every affected product and its fixed version

F5's July 15 out-of-band rollout patched eight vulnerabilities across NGINX and BIG-IP, but the headline act was a trio of memory-safety flaws in NGINX itself, all fixed by the same upgrade. The table below is the core of this post: find your product, read your fixed version, and schedule the upgrade that covers all three CVEs at once.

ProductAffected versionsFixed version
NGINX Open Source (stable)1.30.0 – 1.30.3 (and all releases back to 0.9.6 for CVE-2026-42533)1.30.4
NGINX Open Source (mainline)1.31.2 and earlier1.31.3
NGINX Plus R3737.0.0.1 – 37.0.2.137.0.3.1
NGINX Plus R33 – R36All R33 – R36 buildsR36 P7
NGINX Gateway Fabric1.x and 2.x through 2.6.62.6.7
NGINX Ingress ControllerSeveral maintained branches5.5.3 or 2026-lts-r4
F5 WAF for NGINX5.9.0 – 5.13.35.13.4
NGINX App Protect WAF4.x and 5.x branchesSee F5 advisory K000162097
NGINX Instance Manager2.17.0 – 2.22.1See F5 advisory K000162097

The three CVEs that ship in that single upgrade:

  • CVE-2026-42533 — heap buffer overflow (CWE-122) in the map directive with regex matching. CVSS 9.2 Critical (v4.0) / 8.1 High (v3.1). Unauthenticated, remote, attack complexity high.
  • CVE-2026-60005 — uninitialized memory access in ngx_http_slice_module, a module that is off by default. CVSS 8.8. Triggered by the slice directive running with unnamed regex captures, or during a background cache update.
  • CVE-2026-56434 — use-after-free in ngx_http_ssi_module. CVSS 8.3.

Two numbers deserve emphasis. First, the vulnerable range for the headline CVE stretches back to NGINX 0.9.6 — March 2011, the release where map gained regex support. This bug hid in one of the most-audited codebases on earth for over fifteen years. Second, more than a dozen researchers independently reported it to F5's security team, which tells you how visible the flaw becomes once someone thinks to look at script-engine evaluation order.

As of the mid-July coverage, there was no confirmed in-the-wild exploitation. That is good news with an expiry date: the trigger is a crafted HTTP request against a distinctive, greppable config pattern, which is exactly the kind of thing internet-wide scanners learn to fingerprint within weeks of disclosure.

Are you actually exploitable? The config trigger matters

Here is the honest caveat that keeps this post from being fear-mongering: default deployments are not affected. F5's advisory is explicit that exploitation requires non-default configuration, and that only the data plane is in scope — not the control plane. A stock NGINX with no map blocks is not exploitable. So the real question is whether your config contains the trigger, and the trigger is specific enough to check mechanically.

The overflow fires when a map directive uses regex matching and a string expression references the map's regex capture variables before the map's output variable is evaluated. A second, related path involves a non-cacheable variable appearing in a string expression under certain evaluation orders. In practice, the dangerous shape is a map with a regex match whose numbered captures ($1, $2) get interpolated into another expression ahead of the mapped value.

The crash typically forces a worker restart — a denial of service. Code execution enters the picture when ASLR is disabled or bypassed, which is why F5 scores attack complexity as high rather than low.

To check yourself, start with the broad sweep and narrow down:

bash
# Any regex-bearing map blocks? No output here means the primary trigger is absent.
grep -rn --include="*.conf" -E "map\s+.*~" /etc/nginx/
 
# Unnamed (numbered) captures referenced outside their match block are the
# pattern F5's stopgap targets — see the mitigation section below.
grep -rn --include="*.conf" -E "\$[0-9]" /etc/nginx/ | head -30

If you run a config linter, update it first: gixy 0.2.50, released the day after the disclosure, added a dedicated nginx_cves check for CVE-2026-42533 that flags regex map captures evaluated before the map output. For Kubernetes fleets, remember the blast radius concentrates at the edge: the controller pods terminating external traffic are the ones parsing attacker-controlled bytes through this code path, not your internal services.

One more scope note for Gateway Fabric and Ingress Controller operators: because the flaw is in the underlying NGINX engine rather than the controller logic, you cannot tell from your Gateway, HTTPRoute, or Ingress manifests alone whether generated NGINX config contains a triggering map. The generated config is what matters. Pull it from a running pod and grep the rendered output, not the YAML you applied.

Not that NGINX CVE: 42533 vs. 4342

The NGINX CVE namespace is genuinely confusing right now, because two serious flaws with similar names live in two different codebases with two different fixes. Getting them mixed up means applying the wrong remedy, so here is the contrast stated plainly.

CVE-2026-42533 (this post)CVE-2026-4342
CodebaseCore NGINX (F5/nginx): Open Source + PlusCommunity kubernetes/ingress-nginx controller
Bug classHeap buffer overflow in map + regex script engineComment-based NGINX config injection via Ingress annotations
CVSS9.2 Critical (v4.0)8.8 High
AttackerUnauthenticated remote, crafted HTTP requestAttacker with Ingress-object creation rights
Worst caseWorker crash; RCE if ASLR defeatedConfig injection, RCE in controller, Secrets disclosure (default installs can read all Secrets cluster-wide)
FixUpgrade (patch exists, project alive)Upgrade to v1.13.9 / v1.14.5 / v1.15.1, then migrate off — the project is archived
Affects Gateway Fabric / F5 Ingress Controller?Yes — they embed the vulnerable engineNo — different project entirely

CVE-2026-4342, disclosed in March 2026, was one of the last gasps of the community controller: a bypass of the sanitizers added after the earlier IngressNightmare-era CVEs, using NGINX comment syntax to smuggle injected configuration past validation. We covered that lineage — the March archival, the RCE patches that landed in the project's final weeks, and the fleet-wide audit to find lingering installs — in our ingress-nginx EOL coverage and the CVE-2026-3288 follow-up. If you still have app.kubernetes.io/name=ingress-nginx pods anywhere, that migration remains your most urgent NGINX work; nothing in this post changes that priority.

But notice what the table's last row implies. Teams that already did that migration and chose an NGINX-based landing spot — a natural choice, since F5's Gateway Fabric is a conformant Gateway API implementation — inherited a different NGINX CVE the moment they cut over. "We migrated off ingress-nginx" answers CVE-2026-4342 completely and CVE-2026-42533 not at all. The fix for the old flaw was to leave a codebase; the fix for the new flaw is to patch the codebase you may have just arrived in.

Patch order and the stopgap for teams that can't upgrade today

Upgrades at the edge are the highest-stakes restarts you do — the component being bounced terminates every byte of inbound traffic. Order the work by exposure, outermost first:

  1. Internet-facing data plane first. Upgrade the NGINX instances and controller pods that parse attacker-controlled requests: edge proxies, Gateway Fabric / Ingress Controller data-plane pods, WAF instances. These are the only components that can be reached by the crafted request in the first place.
  2. Then the adjacent F5 products. Instance Manager, App Protect WAF, and WAF for NGINX to their fixed builds per advisory K000162097.
  3. Then everything else running the engine. Internal NGINX sidecars, caching tiers using the slice module, SSI-rendered origins. Lower urgency — no direct attacker input — but the same binary, so close it out in the same window if you can.
  4. Verify, don't assume. nginx -v on hosts, image tags and digests on controller Deployments, and a fleet-wide sweep for stragglers:
    bash
    kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}{" "}{.spec.containers[*].image}{"\n"}{end}' \
      | grep -iE "nginx|gateway-fabric" | sort -u

If you genuinely cannot upgrade an instance this week, F5 offers a configuration-level stopgap rather than leaving you exposed: replace unnamed regex captures with named captures, and reference them only inside the block that holds the regex match. That single change blunts both the map heap overflow and the slice-module memory bug, because both flaws hinge on how unnamed captures are evaluated across expression boundaries. Treat it as what it is — a bridge to the upgrade, not a substitute. The patched binary is the fix; the config change just narrows the window while you schedule the restart.

Two process notes for self-hosted PaaS operators specifically. First, if your platform generates NGINX config from tenant input — custom domains, redirect rules, header rewrites — audit the generator templates, not just the rendered output on one tenant. A triggering map in a template multiplies across every tenant it renders for. Second, pin this to your edge runbook: the next core-NGINX CVE will look exactly like this one, an engine flaw reaching every product that embeds it, and "which of our components embed NGINX?" should be a question you can answer from a list, not from memory.

Your Gateway API implementation is now a security decision

Step back from the version table and the larger lesson is about migration strategy. The ingress-nginx retirement taught the ecosystem that the controller matters; CVE-2026-42533 teaches that the engine underneath the controller matters just as much. Gateway API is a specification, not an implementation — and right now your conformant options include NGINX-based data planes (Gateway Fabric, F5's Ingress Controller in Gateway mode) and Envoy-based ones (Envoy Gateway, Istio, Cilium). A core-NGINX flaw reaches the first group and bounces off the second; a core-Envoy flaw would do the reverse.

That is not an argument for either engine. It is an argument for writing down, as an explicit architectural decision, which engine terminates your traffic and what your patch SLA for it is — instead of inheriting the answer from whichever controller tutorial you followed.

The secondary lesson is about bug longevity. Fifteen years, in NGINX, in a directive every operator has read a hundred times. The map regex path survived because it is old, stable, and boring — the code nobody re-audits. Your fleet has equivalents: the template rendered ten thousand times, the admission webhook nobody has touched since 2024, the base image pinned "temporarily" two years ago. A CVE like this one is a good excuse to pick one of them and re-read it.

Check the matrix, grep your configs, upgrade the edge first — and update the runbook so the next engine-level CVE finds you with a list instead of a memory.

Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.

Related articles

Run this on infrastructure you own

bex is the open-source, AI-native Render alternative — push a git repo and get a running HTTPS service on your own machines.

Get started with bex