Six security fixes. In one release. That’s either evidence the nginx team had a very rough May, or proof that they take security seriously enough to batch fixes and get them out fast. Spoiler: it’s both — and if you’re running nginx mainline, you should upgrade today.
nginx 1.31.0 dropped on 13 May 2026, and it’s not a feature release. It’s a security and compliance release: six CVEs patched, one protocol behaviour change to align with HTTP/2 and HTTP/3 specs, and a segfault bug fix that’ll affect anyone mixing try_files with proxy_pass. Let’s walk through all of it.
What Is nginx 1.31.0? The Mainline vs Stable Thing, Explained
Quick version: nginx has two release branches at any time. If the minor version is even (1.28.x, 1.30.x), it’s the stable branch — tested, conservative, no new features mid-cycle. If it’s odd (1.29.x, 1.31.x), it’s the mainline branch — where active development happens, new features land first, and security fixes appear before stable.
nginx 1.31.0 is the first release of the new mainline cycle. It replaces 1.29.x. If you’re on 1.29.8 or earlier, 1.31.0 is your direct upgrade target. If you’re on stable (1.28.x), security patches will arrive there too — but mainline gets them first.
Running mainline is fine for production if you stay current. Running old mainline is asking for trouble — exactly the kind this release patches.
Six Security Fixes: What’s Actually in nginx 1.31.0
Here’s the full security picture. Some of these are “could be a problem under specific conditions” and some are “this could execute arbitrary code on your server.” Let’s sort them by scariness.
CVE-2026-42945: Heap Buffer Overflow in the Rewrite Module (The Scary One)
A heap memory buffer overflow in ngx_http_rewrite_module — the module that handles rewrite, if, return, and set directives. An attacker could trigger this by sending a specially crafted request, potentially resulting in arbitrary code execution in the worker process.
Yes, “arbitrary code execution” is the technical way of saying “they could run whatever they want on your machine.” If you’re using rewrite rules (and you almost certainly are — WordPress pretty URLs alone count), this one matters. Credit goes to Leo Lin for the discovery.
CVE-2026-40701: Use-After-Free via ssl_ocsp (Also Serious)
If you’re using the ssl_ocsp directive for OCSP certificate status checking, a use-after-free vulnerability could be triggered during DNS server response processing. Use-after-free means nginx reads or writes memory that it already freed — the classic “this memory belongs to someone else now” mistake that leads to worker process memory corruption or a segfault. Also credited to Leo Lin.
If you have ssl_ocsp in your config, treat this as high priority.
CVE-2026-42926: proxy_set_body and HTTP/2 Backend Injection
When using the proxy_set_body directive to override the request body sent to an upstream, an attacker could inject additional data into the proxied request when the backend connection is HTTP/2. This is a request injection vulnerability — the upstream backend receives data the attacker controlled, not just the legitimate request body. Found by Mufeed VH of Winfunc Research.
If you use proxy_set_body and your upstreams speak HTTP/2, patch now.

CVE-2026-42946: Heap Overread via SCGI or uWSGI (Memory Disclosure)
A heap memory buffer overread in ngx_http_scgi_module or ngx_http_uwsgi_module — triggered by a specially crafted response from the backend. The impact: an attacker controlling the backend response could cause limited disclosure of worker process memory contents, or crash the worker with a segfault. If you run Python (Django, Flask) or Ruby apps behind nginx using SCGI or uWSGI, this applies to you. Also credited to Leo Lin.
CVE-2026-42934: charset_map UTF-8 Overread (Limited Memory Disclosure)
A heap buffer overread in the charset conversion code — specifically when nginx decodes responses from UTF-8 using the charset_map directive. The overread could cause limited worker memory disclosure or a segfault. If you use nginx’s built-in charset conversion (most people don’t explicitly, but check your config for charset_map or charset directives), this one’s relevant. Credit to David Carlier.
CVE-2026-40460: HTTP/3 QUIC Connection Migration Address Spoofing
QUIC supports connection migration — a feature where a client can move from one network address to another without reconnecting (useful on mobile devices switching from WiFi to cellular). In affected versions, processing connection migration could cause new QUIC streams to receive a new client address before that address is validated. An attacker could exploit this for address spoofing. Found by Rodrigo Laneth.
If you’ve enabled HTTP/3 (via the quic listen directive), this is worth noting. HTTP/3 is still experimental in mainline nginx — if you’re not running it, this doesn’t affect you.
The Protocol Change: Goodbye, Hop-by-Hop Headers in HTTP/2 and HTTP/3
Beyond the CVEs, there’s one behaviour change: nginx now rejects HTTP/2 and HTTP/3 requests that include hop-by-hop headers — specifically Connection, Proxy-Connection, Keep-Alive, and Transfer-Encoding.
Here’s the context: these headers are HTTP/1.1 concepts that describe per-hop connection management. In HTTP/2 and HTTP/3, they’re explicitly forbidden by the spec. HTTP/2 uses its own multiplexed stream management; there’s no concept of “keep this connection alive” as a header — it’s built in.
Before this change, nginx would silently accept these headers in HTTP/2 and HTTP/3 requests. Now it rejects them with a 400 response. If you have clients or proxies sending these headers over HTTP/2, they’ll get errors after upgrading.
In practice: well-behaved HTTP/2 clients don’t send these headers. If you see 400 errors after upgrading, the culprit is likely a misbehaving client or a misconfigured load balancer upstream. Fix it there — nginx is correct to reject them.
The Bug Fix: try_files + proxy_pass With URI = Segfault
One bugfix in this release: a segmentation fault that could occur in a worker process when both the try_files directive and proxy_pass with a URI component were used in the same config block.
The distinction: proxy_pass http://backend is “proxy to this upstream.” proxy_pass http://backend/path is “proxy to this upstream and rewrite the URI.” The combination with try_files in certain configs could trigger a worker crash. Credit to Jan Svojanovsky for finding it.
If you’ve been seeing unexplained worker process restarts and your config uses try_files alongside a URI-based proxy_pass, this fix is for you.
Should You Upgrade to nginx 1.31.0?
Straight answer:
- On nginx mainline (1.29.x or older mainline): Yes. Upgrade immediately. Six CVEs, including a potential arbitrary code execution in the rewrite module. There’s no scenario where waiting makes sense.
- On nginx stable (1.28.x): Security patches will arrive in the stable branch. Watch the nginx changelog at nginx.org and upgrade when the stable fix appears. Mainline patches usually reach stable within days to weeks.
- Running a distribution package (Ubuntu/Debian default nginx): Wait for your distro’s security advisory and use
apt upgrade nginx. Or — and this is the pitch — switch to our repo for current releases.
Get nginx 1.31.0 from Our Repository
We maintain a Debian and Ubuntu APT repository at deb.myguard.nl with current, optimized nginx builds — including mainline packages, extended module sets, and builds compiled against modern OpenSSL for TLS 1.3 and HTTP/3 support. nginx 1.31.0 is already available.
To add the repository and install:
# Add the repo signing key
curl -sSL https://deb.myguard.nl/gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/myguard-nginx.gpg
# Add the repository (replace bookworm with your distro codename)
echo "deb [signed-by=/usr/share/keyrings/myguard-nginx.gpg] https://deb.myguard.nl bookworm main"
| sudo tee /etc/apt/sources.list.d/myguard-nginx.list
# Install nginx mainline
sudo apt update && sudo apt install nginx
Not sure which package variant to install? Check the how-to-use guide — it covers the available package variants, module sets, and distro-specific notes. The repository page lists all available packages and supported distributions (Debian 11/12/13, Ubuntu 22.04/24.04/24.10).
Our builds ship with an extended module set — Brotli, zstd compression, GeoIP2, ModSecurity, QUIC/HTTP3 support, and more — all built against our hardened OpenSSL. You’re not just getting a version bump; you’re getting a production-grade stack.
Frequently Asked Questions
Is nginx 1.31.0 the stable or mainline release?
Mainline. The odd minor version (31) marks it as a development/mainline release. The current stable branch is 1.28.x. Mainline gets new features and security fixes first; stable gets security fixes once they’re proven. Both are suitable for production — just stay current on whichever branch you choose.
Which CVE in nginx 1.31.0 is the most critical?
CVE-2026-42945 — the heap buffer overflow in ngx_http_rewrite_module — is the most severe. It has a potential for arbitrary code execution, meaning an attacker could theoretically run code in your nginx worker process. CVE-2026-40701 (use-after-free in ssl_ocsp) is close behind. Patch both by upgrading to 1.31.0.
I don’t use rewrite rules. Am I still affected?
You probably do, even if you don’t know it. The ngx_http_rewrite_module handles rewrite, if, return, and set directives. If your config redirects HTTP to HTTPS (return 301 https://...), serves a WordPress installation (which requires rewrite rules), or uses any location block with return, you’re using this module. Upgrade regardless.
Will the HTTP/2 header rejection change break anything?
Only if your clients or upstream proxies are incorrectly sending HTTP/1.1 hop-by-hop headers (Connection, Keep-Alive, Transfer-Encoding, Proxy-Connection) over HTTP/2 or HTTP/3 connections. Well-behaved HTTP/2 clients don’t do this — it’s a spec violation. If you see 400 errors after upgrading, audit your client-side and load balancer configurations first.
I’m on Ubuntu and running `apt show nginx` shows an old version. What do I do?
Ubuntu and Debian package nginx from their own repos, which often lag behind upstream releases by weeks or months. To get current mainline nginx with all security patches, add our repository (instructions above) or the official nginx.org packages. Both provide up-to-date builds. Our repo adds extended modules and hardened OpenSSL on top.
Do I need to restart nginx after upgrading?
Yes — but you can do a zero-downtime reload with sudo nginx -t && sudo systemctl reload nginx. This tests the config first, then reloads. Worker processes serving existing connections finish gracefully; new workers pick up the new binary. No dropped connections. If you’re upgrading the binary (not just config), do a full restart: sudo systemctl restart nginx.
Related Posts
- NGINX Reverse Proxy Configuration: The Complete Setup Guide — proxy_pass, upstream keepalive, caching, and WebSocket proxying with security best practices.
- NGINX Rate Limiting: Protect Your Server from Bots, Scrapers and Brute Force — Stop credential stuffing and DDoS floods before they reach your application.
- NGINX on Debian 13 Trixie: What Changed and How to Upgrade — GCC 14, OpenSSL 3.3, PHP 8.4 — what each change means for your nginx setup.
- NGINX Brotli Compression: Install, Configure and Pre-Compress Static Assets — 15–26% better than gzip: install the Brotli module and tune it for production.