
Disclosure pack and PoC for CVE-2026-86350, an unauthenticated HTTP/2 request header mix-up (CWE-444) in Apache Tomcat 9.0.121, with lab reproduction and patch guidance.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · CVE-2026-86350
Apache Tomcat 9.0.121 - Apache Software Foundation
I am @abraxas_null. Loopback lab. The client is CVE-2026-86350-Abraxas-Labs.py.
HTTP/2 header mix-up. A regression in the CVE-2026-41293 HPACK validation refactor: invalid fields abort decode so later fields never enter the dynamic table. The next stream on the connection then interprets indexes against a desynced table. 9.0.121 (also 10.1.55-59, 11.0.22-25). Fixed in 9.0.122 / 10.1.60 / 11.0.26 by reverting early validation.
| CVE | CVE-2026-86350 · CVE.org |
| CWE | CWE-444 |
| CVSS | Critical: 9.1 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N |
| Product | Apache Tomcat |
| Affected | all versions through 9.0.121 (inclusive) |
| Patched | 9.0.122 and later |
| Auth | unauthenticated |
| License | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 only |
Unauthenticated HTTP/2. Send a HEADERS block with an invalid field, then a second stream on the same connection. Headers mix, or the connection GOAWAYs / RSTs. That is request smuggling against anything sitting behind this connector. HTTP/1.1 only is not this CVE.
I mapped HpackDecoder / HPackHuffman on 9.0.121, then hit h2c with prior-knowledge preface. Stream 1: invalid field value (trailing space) then a marker. Stream 2 indexes the marker.
Fail-controls already in the lab: stream 1 RST and stream 2 clean 200 is patched 9.0.122; HTTP/1.1 only never reaches the decoder; a reverse shell is not this CVE. Apache also lists removing the examples webapp as a mitigation for the header oracle, not as a patch.
Port 18095. Tomcat 9.0.121, HTTP/2 enabled, examples webapp present for the header oracle.
Target only 127.0.0.1:18095 (or the loopback you bound).
cd lab
docker compose up --force-recreate
python3 ../CVE-2026-86350-Abraxas-Labs.py
Witness: After an invalid HTTP/2 field on stream 1, stream 2 is not a clean 200 (GOAWAY, RST, or marker mix-up).
Ways to lose without learning anything:
Update Apache Tomcat to 9.0.122 (or 10.1.60 / 11.0.26) or newer. Re-run CVE-2026-86350-Abraxas-Labs.py against the patched build: stream 2 must stay a clean 200 after stream 1 RST.
github.com/apache/tomcat/commit/5adadc4ef413d5050f664d40800bbff74bd5d5ed
Abraxas Labs: abraxaslabs.tech · github.com/abraxas · @abraxas_null
GNU Affero GPL v3.0. See LICENSE.
The client talks to loopback. Using it against systems you do not own is not authorized by Abraxas Labs. No warranty.