If you run nginx as a reverse proxy with HTTP/3 enabled, the 15 September 2026 release of 1.31.6 is not a routine bump - it’s a security fix you should read, not skim. The release closes CVE-2026-90439, a heap buffer overflow in the HTTP/3 (ngx_http_v3_module) code path that only triggers when nginx is linked against OpenSSL 3.5.0 or earlier.[1] If you’re on a distribution nginx that still bundles an older OpenSSL and you’ve turned on QUIC serving, the vulnerable code is sitting in a worker process in front of your traffic.

Update, 17 October 2026: 1.31.6 / 1.30.5 are no longer the versions to land on. On 14 October 2026 nginx shipped 1.31.7 (mainline) and 1.30.6 (stable), which fix five more medium-severity CVEs (CVE-2026-15176, CVE-2026-93479, CVE-2026-95101, CVE-2026-97629, CVE-2026-97205) that affect 1.31.6 and 1.30.5 as well; one of them (CVE-2026-95101) is again in HTTP/3 request-body handling.[3][6] The checks below for CVE-2026-90439 still hold, but upgrade straight to 1.31.7 / 1.30.6.

This is a complement to our reverse-proxy configuration guide and the Control API reload guide - the assumption here is that you already have nginx running. What follows is the minimum you need to know about the flaw, how to check whether your host is in scope, and the exact steps to get out from under it.

What CVE-2026-90439 actually is

CVE-2026-90439 is a heap buffer overflow in the module that powers HTTP/3 - the ngx_http_v3_module that runs HTTP/3 over the QUIC transport. The overflow can happen while nginx processes a TLS handshake when the build uses OpenSSL versions <= 3.5.0, under certain configurations.[2]

Two things about it are worth being precise about, because they shape how urgent this is:

  • It’s not reliably weaponizable. The CVE record is explicit that the overflow “can happen in a non-deterministic manner that is beyond the attacker’s control."[2] That’s not a clean universal remote-code-execution primitive; in practice it tends to manifest as a worker-process restart (a denial of service) or, at worst, limited data corruption in the worker.
  • It’s a data-plane issue only. There is no control-plane exposure; remote attackers can aim a crafted handshake at a vulnerable server to cause a DoS or limited data corruption, but the advisory does not describe a path to the control plane.[2]

The severity is medium on the nginx advisories page, and F5 rates it CVSS 6.5 (3.1) / 6.9 (4.0) - network-attackable, low complexity, no privileges, no user interaction.[2][3] So “medium,” yes, but it’s remotely reachable on a web server that speaks HTTP/3. For a reverse proxy with QUIC exposed, that’s squarely inside the blast radius you should not sit on.

Which versions are in scope

From the nginx security advisory:[3]

  • Vulnerable: nginx 1.29.2 through 1.31.5 (mainline).[3] On the stable branch, everything before 1.30.5 is in scope - the CVE record lists 1.30.4 as the affected stable build.[2]
  • Not vulnerable: 1.31.6+ and 1.30.5+.

Two branches, one fix: nginx released 1.31.6 (mainline) and 1.30.5 (stable) on the same day, both carrying the same security note - “a heap memory buffer overflow might occur in a worker process under certain configurations when using HTTP/3 with OpenSSL 3.5.0 and earlier (CVE-2026-90439)."[1]

One more condition narrows the scope further: HTTP/3 has to actually be compiled in and enabled. The ngx_http_v3_module is not built by default - you enable it at build time with --with-http_v3_module.[4] So a stock distro nginx that never had the module compiled can’t hit this bug even if the version number looks vulnerable. The overflow needs the v3 module present, HTTP/3 negotiated on at least one server block, and a vulnerable OpenSSL.

Am I affected? Check these three things

Don’t reason about it from memory - read it off the box. Three quick commands cover it.

1. What nginx version are you running?

nginx -v
# nginx version: nginx/1.31.5   → in scope (mainline)
# nginx version: nginx/1.30.5   → patched for this CVE, but upgrade to 1.30.6 (Oct 2026 CVEs)

2. Was the HTTP/3 module actually built in?

nginx -V 2>&1 | grep -o '\-\-with-http_v3_module'

If this prints nothing, the module isn’t compiled and this CVE can’t reach you through HTTP/3 - the fix is still worth applying, but the urgency drops sharply.

3. Which OpenSSL is nginx linked against?

nginx -V 2>&1 | grep -iE 'openssl|OpenSSL'
openssl version

nginx -V prints the OpenSSL it was built with (e.g. built with OpenSSL 3.5.0). The CVE needs OpenSSL <= 3.5.0.[2] If your nginx is linked against OpenSSL 3.5.1 or newer, the vulnerable path isn’t active even on an in-scope nginx version.

The HTTP/3 code in the OpenSSL-linked path is what matters here - the linked OpenSSL version, not whatever openssl version says system-wide. They usually match on a standard distro install, but check both and trust nginx -V.

4. Is HTTP/3 actually enabled in your config? (if the module is built)

grep -rnE 'listen .*(quic|http3)' /etc/nginx/sites-enabled/
grep -rn 'http3' /etc/nginx/

HTTP/3 is served when a server block has listen 443 quic reuseport; (or listen ... http3;), which is how the module’s own example configures it.[4] If you have listen ... quic anywhere, and the version and OpenSSL checks above say you’re vulnerable, you’re in scope - right now.

The full at-risk profile is narrow but real: nginx 1.29.2–1.31.5 (or stable below 1.30.5) + --with-http_v3_module compiled in + listen ... quic in config + OpenSSL <= 3.5.0. That’s a proxy that actively speaks HTTP/3 and is linked against a pre-fix OpenSSL.

Upgrade: patched releases on both branches

Both fixed versions shipped on 15 September 2026, available as source and as the usual binary packages.[1][5] The upgrade is the same routine as any nginx security bump - the section below assumes you got 1.31.6 (or 1.30.5) from a repository rather than compiling it.

# Debian / Ubuntu
sudo apt update
sudo apt install nginx=1.31.7*          # security-fixed mainline (14 Oct 2026; 1.31.8 also fine); or just `sudo apt upgrade`

If your distro pins an older stable nginx (a common situation - Ubuntu ships older mainline/stable stacks), you have two real options: move to nginx.org’s official packages for the needed branch, or build with a newer OpenSSL. The module’s docs note that HTTP/3 requires OpenSSL 1.1.1 or higher, and 0-RTT support needs OpenSSL 3.5.1 or higher.[4] That 3.5.1+ floor for 0-RTT is a useful coincidence here - an OpenSSL at or above 3.5.1 is exactly the build that sits outside this CVE’s affected OpenSSL range.

Validate the config before you touch the running process. The Control API guide’s advice still applies: test a candidate config before applying it.

sudo nginx -t           # check the config parses cleanly first

Then reload or restart. For a security fix, a restart with the new binary is the unambiguous choice - a reload keeps the old binary serving new connections during the swap and only recycles workers on a signal. That’s fine for config changes; for a security patch you want the patched binary actually terminating connections.

# cleanest for a security patch: full restart
sudo systemctl restart nginx

# or, if you're confident and want zero-downtime worker recycling
sudo systemctl reload nginx

Confirm the version that’s now serving:

nginx -v
# nginx version: nginx/1.31.7
nginx -V 2>&1 | grep -iE 'openssl'
# built with OpenSSL 3.5.0   ← `nginx -V` is the truth for the linked lib

If nginx -V still reports the old OpenSSL after the nginx package upgraded, your distributor rebuilt nginx against a distro OpenSSL rather than bundling a new one - in that case the nginx-side fix in 1.31.6/1.30.5 is what actually closes the CVE, so the nginx version is the one that must change.

One behavior change ships with both releases worth knowing even once you’re patched: “now the QUIC transport parameters extension received in an SSL connection is always ignored."[1] It’s a small hardening that closes a TLS/QUIC-handshake confusion vector in the same zone.

Can’t upgrade right now? Disable HTTP/3

The honest answer is that the only fixed state is a patched nginx (or OpenSSL above 3.5.0). But the vulnerable code only runs when a server block actually negotiates HTTP/3. If you can’t upgrade your nginx binary immediately, the biggest thing you can do is stop serving HTTP/3 today:

# before (vulnerable path active where HTTP/3 is negotiated)
# listen 443 quic reuseport;
# listen 443 ssl;

# after (HTTP/3 turned off; clients fall back to HTTP/2 / HTTP/1.1)
# listen 443 ssl;

Comment out (or delete) the quic parameter on the listen line and remove any http3 on; directive, leaving the plain listen 443 ssl; block that was already serving TLS. Run nginx -t, then reload. Clients that would have spoken HTTP/3 now negotiate HTTP/2 instead; the vulnerable handshake path is no longer reachable.

This is a drop in protocol support you’re making on purpose, so weigh it against how much of your client base actually lands on HTTP/3 - for most sites it’s a small slice, and HTTP/2 covers the rest fine. It’s also exactly what we did in the reverse-proxy guide’s server block, which uses listen 443 ssl; + http2 on; and no QUIC.

Two honest caveats about the “disable it” route:

  • It’s a mitigation, not a fix. The moment you re-enable quic, the vulnerable path is back unless nginx (or the linked OpenSSL) is patched. Treat disabling HTTP/3 as a temporary stopgap, with upgrade as the real landing.
  • Don’t invent a half-state. There’s no official “safe subset” of HTTP/3 settings that the advisory blesses for vulnerable nginx+OpenSSL builds. Either you test and patch, or you drop HTTP/3 until you can. Don’t leave a quic listener thinking a smaller buffer or fewer streams makes it safe - the overflow is in the handshake path, not in anything you can tune away.

What this connects to

This fix lands in the same nginx release line as the features our other guides cover - 1.31.5 added the Control API and predicate locations, and 1.31.6 hardens the HTTP/3 side that sits on top of a properly configured reverse proxy. If you’re adopting any of the newer mainline features, you’re on the mainline branch anyway, which means the 1.31.6 fix is one apt upgrade away.

The short version

CVE-2026-90439 is a medium-severity heap buffer overflow in nginx’s HTTP/3 module, reachable remotely, that only fires when nginx is linked against OpenSSL 3.5.0 or earlier. Affected: nginx 1.29.2–1.31.5 (mainline) and 1.30.x below 1.30.5 (stable), provided the v3 module is compiled in, HTTP/3 is enabled in config, and OpenSSL is <= 3.5.0. If that’s your box, upgrade - today that means 1.31.7 or 1.30.6, which include this fix plus the five October 2026 CVEs[6] - validate with nginx -t, restart, and confirm with nginx -v + nginx -V. If you genuinely can’t upgrade yet, disable HTTP/3 (drop quic from listen) and let clients fall back to HTTP/2 until you’re patched. Don’t leave a vulnerable quic listener running while you weigh the options.

Sources

  1. nginx - Changes (release 1.31.6, 15 Sep 2026: CVE-2026-90439 note; QUIC transport-parameters change). https://nginx.org/en/CHANGES - checked 2026-09-30
  2. CVE-2026-90439 record (description, affected OpenSSL <= 3.5.0, non-deterministic overflow, DoS/limited corruption, CVSS). https://www.cve.org/CVERecord?id=CVE-2026-90439 - checked 2026-09-30
  3. nginx - Security advisories (affected 1.29.2–1.31.5, not vulnerable 1.31.6+/1.30.5+; severity medium). https://nginx.org/en/security_advisories.html - checked 2026-09-30
  4. nginx - Module ngx_http_v3_module (--with-http_v3_module, not built by default, listen ... quic, OpenSSL 1.1.1+ / 0-RTT 3.5.1+). https://nginx.org/en/docs/http/ngx_http_v3_module.html - checked 2026-09-30
  5. nginx - download (source + binary packages; mainline 1.31.x / stable 1.30.x). https://nginx.org/en/download.html - checked 2026-09-30
  6. nginx - Changes with nginx 1.31.7 / 1.30.6 (14 Oct 2026: CVE-2026-15176, CVE-2026-93479, CVE-2026-95101, CVE-2026-97629, CVE-2026-97205; all not vulnerable from 1.31.7+/1.30.6+ per the advisories page). https://nginx.org/en/CHANGES ; https://nginx.org/en/security_advisories.html - checked 2026-10-17