
Proof-of-concept exploit, root-cause analysis and one-line patch for CVE-2026-97629, an nginx TLS session-ticket forgery that bypasses client-certificate (mTLS) authentication.
One line of C. One forged TLS session. Found, proved end to end, and coordinated to a fix by PhiNode Labs.
A proof-of-concept exploit, the root-cause analysis, the one-line patch and the reproduction evidence for CVE-2026-97629, a TLS session-ticket forgery in nginx that can bypass client-certificate (mutual-TLS) authentication. Disclosed to F5 under coordinated disclosure and credited to PhiNode Labs.
Read the full write-up: https://phinode.io/nginx-cve-2026-97629.html
"F5 acknowledges PhiNode Labs for bringing this issue to our attention and following the highest standards of coordinated disclosure." — F5 Security Advisory K000162606
| CVE | CVE-2026-97629 |
| Advisory | F5 K000162606 · GHSA-862p-pr69-37gq |
| Severity | CVSS 3.1 6.5 / CVSS 4.0 8.3 (F5). Up to 10.0 on mutual-TLS deployments |
| Weakness | CWE-908 — use of uninitialized resource |
| Component | ngx_http_ssl_module — ngx_ssl_rotate_ticket_keys() |
| Affected | nginx 1.23.2 – 1.31.6, NGINX Plus up to R37 (37.0.5), and F5 products built on nginx |
| Fixed | nginx 1.31.7 and 1.30.6, NGINX Plus 37.0.5.1 / 37.1.0.1 |
| Credit | PhiNode Labs — [email protected] |
To resume TLS connections quickly, nginx seals a session ticket with a
rotating key and keeps three such keys per worker: current, previous, next.
During rotation, ngx_ssl_rotate_ticket_keys() copied only two of the three
slots into each worker; the third was never written after startup. On a default
Linux build that memory is all zeros — the same, predictable value on every
worker in every default deployment.
The decrypt callback scans all three slots. A client can submit a forged ticket whose 16-byte key name is all zeros, match the untouched third slot, and have nginx unseal it with all-zero AES and HMAC keys that anyone can guess. From there an attacker forges a valid session with keys they choose and resumes an encrypted connection without completing a real handshake. Where a server trusts a client certificate to decide who gets in, that check is bypassed.
The fix is a single character:
ngx_memcpy(keys->elts, cache->ticket_keys,
- 2 * sizeof(ngx_ssl_ticket_key_t));
+ 3 * sizeof(ngx_ssl_ticket_key_t));
See patch/ for the ready-to-apply diff.
nginx serves roughly a third of all websites. The impact F5 credits — bypassing client-certificate verification — lands hardest on mutual TLS: open banking (PSD2 / FAPI), healthcare data exchange, 5G core network functions, Kubernetes ingress, zero-trust and device fleets, where a certificate is the whole access decision. On those deployments the forgery is a full client-authentication bypass, the maximum-severity reading.
Everything is local, on a loopback listener with a throwaway self-signed
certificate. See poc/ for the exploit and evidence/
for captured output: nginx accepting the all-zero key, the abbreviated
handshake, and a full read/write over the forged session (decrypted HTTP 404).
cd poc
python3 make_forged_session.py # patch the session_id_context
python3 forge_ticket.py # -> VERDICT: TICKET ACCEPTED
python3 forge_ticket_full.py # -> full read/write over the forged session
ssl_session_tickets off;ssl_session_ticket_key files that you rotate yourself.A server is only exposed if all hold: a vulnerable version, a
ssl_session_cache shared:…, tickets on with no key file, and certificates
that decide access.
| Date | Event |
|---|---|
| Jun 2026 | PhiNode Labs identifies the slot mismatch and proves it end to end |
| Aug 2026 | Reported to F5 SIRT; forwarded to NGINX Product Engineering |
| Sep 2026 | NGINX PE classifies it as a vulnerability |
| Oct 12, 2026 | CVE-2026-97629 assigned (F5 NPS-179) |
| Oct 14, 2026 | F5 publishes K000162606; fixes ship in nginx 1.31.7 / 1.30.6 |
This proof of concept is published after the fix shipped and with F5's coordinated release, for defenders to verify their own servers. Do not use it against systems you do not own or operate.
PhiNode Labs is an applied program-analysis research lab. We find the defects scanners and language models walk past — no injected string, no obvious bad function, just a size that should have been three and was two — by reasoning about what a program's memory actually holds at runtime. No claim without a witness.
Keywords: CVE-2026-97629, nginx, TLS session ticket, session ticket forgery, session resumption, mutual TLS, mTLS, client certificate bypass, ngx_http_ssl_module, ngx_ssl_rotate_ticket_keys, F5, NGINX Plus, proof of concept, PoC, exploit, CWE-908, PhiNode Labs, program analysis.