Five weeks after NGINX Rift had half the internet scrambling, F5 pushed another out-of-band advisory. Two critical bugs this time, both scoring 9.2 on CVSS v4, both remotely exploitable without authentication. One lives in the HTTP/3 code path. The other lives in how NGINX talks HTTP/2 to your backends. I spent the past day pulling apart both bugs, cross-checking the official nginx.org changelog against F5’s advisories, and digging through the affected-version matrix that spans seven different product lines. Here’s what’s actually going on, what it takes to get hit, and what to do about it before someone else figures out the exploit chain.

Nginx Logo
Nginx Logo

If you run NGINX Open Source, NGINX Plus, NGINX Gateway Fabric, Ingress Controller, or anything sitting behind F5’s WAF/DoS line for NGINX, this one’s for you.

What landed, and when

F5 published its out-of-band security notification on June 17, 2026, with an update the following day. This wasn’t part of F5’s regular quarterly notification cycle – out-of-band releases are reserved for things F5 doesn’t want sitting in a queue. The advisory bundles two critical memory-corruption bugs, two high-severity configuration-injection bugs in Gateway Fabric, and a low-severity information disclosure bug, all fixed in the same nginx 1.31.2 / 1.30.3 release cut on the same day.

I want to be upfront about something most of the coverage glossed over: F5 has not flagged either critical bug as exploited in the wild. But NGINX Rift (CVE-2026-42945), an 18-year-old bug in the rewrite module, sitting untouched since nginx 0.6.27 back in 2008, went from public disclosure to active exploitation in days last month. Researchers had a working proof of concept reverse-engineered from the patch diff almost immediately. There’s no reason to assume these two will be slower.

CVE-2026-42530: the QPACK use-after-free

This is the one that should worry anyone running HTTP/3.

The bug, in plain terms: ngx_http_v3_module has a use-after-free condition (CWE-416) that triggers when a client reopens a QPACK encoder stream mid-session using a specially crafted HTTP/3 exchange. The freed memory gets touched again, and depending on what’s sitting in that memory region by the time it’s reused, you get a worker crash or, if ASLR is off or already defeated, code execution.

CVE-2026-42530 PoC (Source: X/Twitter)

To understand why this is nastier than it sounds, you need a quick refresher on how QPACK actually works.

QPACK and why stream lifecycle matters: HTTP/2 compresses headers with HPACK, which assumes strictly ordered, single-stream delivery – TCP guarantees that. HTTP/3 runs over QUIC, where streams can arrive out of order and get reset independently, so HPACK’s ordering assumptions break. QPACK was designed specifically to tolerate that. It splits header compression state across two dedicated unidirectional streams: the encoder stream, which carries instructions like Insert With Name Reference, Insert With Literal Name, Set Dynamic Table Capacity, and Duplicate; and the decoder stream, which carries acknowledgments back – Header Acknowledgement, Stream Cancellation, Insert Count Increment. The dynamic table itself lives independently of any single request stream, which is the whole point: a header value indexed early in the connection can still be referenced by a request that arrives much later, even out of order.

That independence is also where this bug lives. Stream lifecycle management for QUIC is fundamentally harder than for TCP because streams can be reset (RESET_STREAM) or aborted on the receiving side (STOP_SENDING) asynchronously, and a “closed” stream in QUIC terms doesn’t always mean the server-side state object tied to it has actually been torn down and reclaimed yet. When a client reopens a QPACK encoder stream – something that’s only supposed to happen once per connection, but which a malicious client can force by violating that assumption deliberately, the server’s bookkeeping structure for the previous encoder stream instance can get freed while a reference to it is still live elsewhere in the connection’s processing pipeline. The next time that stale pointer gets dereferenced – to apply an encoder instruction, update table state, whatever the code path does next, you’re reading or writing freed heap memory.

Why ASLR matters here, and why it isn’t a full mitigation: a bare use-after-free gives an attacker a memory corruption primitive, not code execution by itself. To turn it into RCE you typically need two more things: a way to control what gets allocated into the freed chunk before it’s reused (heap grooming, sometimes called heap feng shui), and a way to either know or guess where useful gadgets or function pointers live in memory which is exactly what ASLR is supposed to prevent. F5’s own language – “execute code on systems with ASLR disabled or when the attacker can bypass ASLR” is doing a lot of work in that second clause. ASLR bypass on a remote, network-facing service usually means chaining in an information leak from somewhere else, which raises the bar but doesn’t close the door. Worth noting that the CVSS v4 vector F5 publishedAV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H flags Attack Complexity: High. That’s the scoring system’s way of acknowledging the race-condition-and-ASLR reality: network vector, no privileges, no user interaction, but getting from “crash” to “shell” takes real exploitation work, not a single crafted packet.

What every deployment gets for free, with zero exploitation skill required, is the denial-of-service outcome: trigger the UAF, worker process dies, NGINX respawns it. Repeat that fast enough across enough connections and you’ve got a remotely triggerable worker-recycling DoS that doesn’t need ASLR bypass at all.

Mitigation if you can’t patch immediately: disable HTTP/3. Pull quic off every listen directive. That removes ngx_http_v3_module from the request path entirely, which kills the bug along with HTTP/3 support – not pretty if you’ve invested in QUIC for latency reasons, but it’s a complete fix until you can upgrade.

CVE-2026-42055: the HTTP/2-to-backend heap overflow

This one’s quieter on paper – nginx.org’s own advisory page actually rates it “medium” severity internally, against F5’s CVSS v4 score of 9.2 but it’s arguably more dangerous in practice because the configuration that triggers it is one a lot of API gateways and Kubernetes ingress setups will recognize.

The trigger conditions, precisely: you need proxy_http_version 2 or grpc_pass in play meaning NGINX is speaking HTTP/2 to an upstream, whether as a reverse proxy fronting an HTTP/2 service or as a gRPC gateway combined with ignore_invalid_headers off and a large_client_header_buffers size configured above 2 MB. All three have to line up.

That middle condition trips people up because the directive name reads backwards from what it does. ignore_invalid_headers defaults to on, and on means NGINX silently drops header fields with invalid names (anything outside letters, digits, hyphens, and optionally underscores) before they ever reach deeper processing. Flip it to off, and NGINX stops dropping them, it processes those malformed headers and, in proxy configurations, forwards them upstream instead of discarding them at the edge. Operators usually do this on purpose: legacy backends that expect headers with dots or other RFC-adjacent-but-technically-invalid characters, internal APIs that don’t follow the spec strictly, that kind of thing.

large_client_header_buffers defaults to four buffers around 8K each on most platforms – nowhere near the 2 MB threshold this bug needs. Pushing it past 2 MB is a deliberate operator choice too, and it’s not a rare one. Anyone fronting OAuth flows with bulky JWTs, SAML assertions with embedded certificates, or service-mesh deployments where trace-context headers balloon under load has a real reason to crank this value up. Put plainly: the exact people most likely to be running large header buffers – API gateways, identity-heavy backends, observability-instrumented service meshes are disproportionately likely to also have the ignore_invalid_headers off flexibility turned on, because both changes get made by the same kind of “stop nginx from rejecting my weird-but-legitimate traffic” operational pressure.

With both flags set, a specially crafted request with malformed or oversized HTTP/2 header content reaches ngx_http_proxy_v2_module or ngx_http_grpc_module without getting filtered first, and the buffer-handling logic for header data built around assumptions that don’t hold once you’ve both widened the buffer ceiling and let invalid header content through overflows on the heap. Heap overflows of this kind typically corrupt adjacent allocator metadata or neighboring live objects, which is the standard launchpad for control-flow hijacking, again gated by the same ASLR caveat as the QPACK bug.

Mitigation if you can’t patch immediately: strip ignore_invalid_headers off from your config (go back to the default), or drop large_client_header_buffers below 2 MB. F5 frames these as alternatives, you only need one but if your environment genuinely needs both large buffers and permissive header handling for legitimate traffic, you’ve got no real mitigation short of patching, and you should treat that as a signal to prioritize the upgrade over the workaround.

One detail nobody else seems to have pulled out: the official nginx.org changelog for 1.31.2 credits Mufeed VH of Winfunc Research with the CVE-2026-42055 find. Worth knowing who’s been poking at this code path if you’re trying to gauge how mature the public understanding of the bug already is.

The quiet third bug riding in the same patch

ngx_http_charset_module picked up a fix for CVE-2026-48142 in the same release – a heap buffer over-read, not an overflow, triggered while decoding a specially crafted response body from UTF-8 through the charset_map directive. Low severity on nginx.org’s own scale, but it’s an information-disclosure primitive: worst case, limited leakage of worker process memory, which in a sufficiently determined exploit chain is exactly the kind of leak you’d use to defeat ASLR ahead of throwing the QPACK bug or the gRPC overflow at the same box. Credited to Han Yan of Xiaomi and p4p3r of CYBERONE in the official changelog. If you’re patching for the two critical bugs anyway, this one rides along for free – but don’t dismiss it as irrelevant just because its standalone CVSS is low.

The Gateway Fabric config-injection pair

Separate from the memory-corruption bugs, F5 also patched CVE-2026-11311 and CVE-2026-50107 in NGINX Gateway Fabric – the Kubernetes Gateway API implementation that uses NGINX as its data plane. Both are high severity, both require an authenticated attacker with permission to modify the relevant Custom Resource (specifically validation gaps around OIDC extra arguments and server-token handling in the AuthenticationFilter and NginxProxy CRDs for the first bug, and access-log format validation in NginxProxy for the second), and both let that attacker inject arbitrary NGINX configuration directives into the generated config.

That’s a meaningfully different threat model from the two RCE bugs – it needs an authenticated, somewhat-privileged actor inside your cluster’s RBAC boundary rather than an anonymous internet attacker. But in multi-tenant Kubernetes environments where different teams hold CRD-edit permissions on shared Gateway resources, “authenticated” doesn’t mean “trusted,” and F5’s own description of the impact is blunt: successful exploitation can expose data from the NGINX pod’s filesystem, redirect proxied traffic to attacker-controlled endpoints, or wedge the data plane into a state where it can’t reload, which is a DoS by a different mechanism than the memory-corruption bugs entirely. Both are fixed in Gateway Fabric 2.6.4, and the upstream changelog ties the fixes directly to expanded CRD field validation – not a code-execution patch, a parsing-and-allow-listing patch, which tracks with the root cause being insufficient input validation rather than a memory-safety issue.

Why the severity numbers don’t agree with each other

You’ll see CVE-2026-42530 and CVE-2026-42055 reported with three different numbers depending on the source: CVSS v3.1 base score of 8.1, CVSS v4.0 base score of 9.2, and nginx.org’s own internal severity labels of “major” and “medium” respectively. None of these are wrong – they’re measuring different things. CVSS v4 changed how it weighs attack complexity and the separation between vulnerable-system and subsequent-system impact, which tends to push network-exploitable memory-corruption bugs higher than v3.1 did for the same underlying flaw. nginx.org’s internal labeling, meanwhile, predates CVSS v4 adoption in most of the industry and reflects the project’s own judgment about exploit reliability, not a recalculated score. If your vulnerability management pipeline is keyed to a single CVSS feed, it’s worth checking which version it’s pulling, because “medium” and “critical” landing on the same bug from different legitimate sources is going to confuse a lot of patch-prioritization meetings this week.

Affected versions

ProductVulnerableFixed
NGINX Open Source1.31.0–1.31.1 (CVE-2026-42530); 1.30.0–1.30.2 and 1.31.1 (CVE-2026-42055)1.31.2 / 1.30.3
NGINX Plus37.0.0–37.0.1; R33–R3637.0.2.1 / R36 P6
NGINX Gateway Fabric2.0.0–2.6.3 (both CVEs); 1.3.0–1.6.2 unpatched2.6.4
NGINX Ingress Controller3.5.0–3.7.2, 4.0.0–4.0.1, 5.0.0–5.5.0Patches pending – mitigate
NGINX Instance Manager2.17.0–2.22.0Patches pending – mitigate
F5 WAF for NGINX5.9.0–5.13.1Patches pending – mitigate
NGINX App Protect WAF4.10.0–4.16.0, 5.2.0–5.8.0Patches pending – mitigate
F5 / NGINX App Protect DoS4.3.0–4.7.0, 4.9.0Patches pending – mitigate

That second column of “patches pending” entries is the part I’d flag hardest to anyone running an internet-facing F5 WAF or App Protect deployment in front of NGINX. You’re stuck on the two config-level mitigations – Disabling HTTP/3 and fixing the header-buffer/invalid-headers combo until F5 ships dedicated builds. Don’t assume a WAF in front of the bug protects you against it; a WAF inspects application-layer traffic, it doesn’t patch a use-after-free in the proxy engine sitting behind it.

What to Do Now

Patch NGINX Open Source and Plus first. That’s the easiest lift and covers the broadest base. Gateway Fabric operators should move to 2.6.4 in the same pass since it picks up both the memory-corruption fixes and the CRD validation fixes together. For everything still waiting on a vendor build – Ingress Controller, Instance Manager, the WAF and DoS products – apply both mitigations simultaneously rather than picking one: disable HTTP/3 on the listener side, and audit every server block for ignore_invalid_headers off paired with an oversized large_client_header_buffers. If you genuinely need both for legitimate traffic, that combination is now a known attack surface, and the honest move is treating the upgrade as urgent rather than optional.

Monitor for the cheap signal first – repeated, unexplained worker process restarts are the DoS-tier exploitation of the QPACK bug, and they’re visible in your error log long before anyone’s attempting the harder RCE path. If you’re seeing worker churn on an HTTP/3-enabled listener right now, that’s worth investigating today, not after the patch window.

This post first appeared at - The CyberSec Guru