Apache Tomcat patches a JNDIRealm auth bypass and HTTP/2 and AJP response mix-ups
Contents
TL;DR
What happened On October 20, 2026, Apache Tomcat published eight CVEs for 9.x, 10.1.x and 11.x. Three are rated Important:
- CVE-2026-101296: JNDIRealm configured with a non-GSSAPI SASL mechanism authenticates users without the correct password
- CVE-2026-101356: an error during async processing over HTTP/2 can mix up requests and responses between users
- CVE-2026-103119 (11.x only): a large non-blocking write over AJP can leak part of one response into the next request on the connection
What to do Upgrade to 9.0.123, 10.1.61 or 11.0.27. All three were released on October 12
Who is exposed Each Important issue needs a specific setup. In the default server.xml, the connector with HTTP/2 enabled and the AJP connector are both commented out
On October 20, 2026, Apache Tomcat listed eight vulnerabilities on its security pages for 9.x, 10.1.x and 11.x (Apache Tomcat 11.x, 10.x, 9.x).
The fixes had already shipped eight days earlier in 9.0.123, 10.1.61 and 11.0.27, released on October 12. Tomcat rated three of the issues Important and five Low.
Tomcat is the server that runs Java web applications (Servlets), and it is also the embedded server in a default Spring Boot web setup.
The eight CVEs
| CVE | Issue | Severity |
|---|---|---|
| CVE-2026-101296 | JNDIRealm configured with a non-GSSAPI SASL mechanism authenticates without the correct password | Important |
| CVE-2026-101356 | After an error during async processing over HTTP/2, requests and responses can be mixed up between users | Important |
| CVE-2026-103119 | Over AJP, a large non-blocking response write can be split across the current request and the next request on the same connection | Important |
| CVE-2026-93446 | TLS 1.3 connections can fail intermittently | Low |
| CVE-2026-88041 | HTTP/2 trailer fields (headers sent after the body) from a previous request leak into a later request | Low |
| CVE-2026-74049 | The <c:redirect> replacement in Jasper (Tomcat’s JSP engine) does not stop processing the rest of the page after the redirect | Low |
| CVE-2026-74048 | With OpenSSL-FFM, a failure to enable FIPS (the US government standard for cryptographic modules) mode does not stop start-up, and Tomcat runs without FIPS | Low |
| CVE-2026-80353 | A race when the APR connector (the connector built on a native library) creates a Unix domain socket lets an unauthorized local user access the socket | Low |
Affected versions differ by branch. The ranges below are taken from each branch’s security page, and - means the CVE is not listed for that branch.
The M in 9.0.0.M1 or 11.0.0-M1 indicates a milestone build released before the stable versions.
| CVE | 9.0.x | 10.1.x | 11.0.x |
|---|---|---|---|
| CVE-2026-101296 | 9.0.0.M1 to 9.0.122 | 10.1.0-M1 to 10.1.60 | 11.0.0-M1 to 11.0.26 |
| CVE-2026-101356 | 9.0.118 to 9.0.122 | 10.1.55 to 10.1.60 | 11.0.22 to 11.0.26 |
| CVE-2026-103119 | - | - | 11.0.0-M25 to 11.0.26 |
| CVE-2026-93446 | 9.0.90 to 9.0.122 | 10.1.25 to 10.1.60 | 11.0.0-M21 to 11.0.26 |
| CVE-2026-88041 | 9.0.92 to 9.0.122 | 10.1.27 to 10.1.60 | 11.0.0-M23 to 11.0.26 |
| CVE-2026-74049 | 9.0.0.M1 to 9.0.122 | 10.1.0-M1 to 10.1.60 | 11.0.0-M1 to 11.0.26 |
| CVE-2026-74048 | 9.0.92 to 9.0.122 | 10.1.22 to 10.1.60 | 11.0.0-M14 to 11.0.26 |
| CVE-2026-80353 | 9.0.47 to 9.0.122 | - | - |
The same race in setting Unix domain socket permissions was fixed earlier as CVE-2026-65183.
That fix did not cover the APR connector, and CVE-2026-80353 is the follow-up fix. It appears only on the 9.x page.
JNDIRealm authentication bypass (CVE-2026-101296)
A Realm is how Tomcat checks user names, passwords and roles (groups of permissions). JNDIRealm does that check by querying an LDAP directory.
When the userPassword attribute is not set, JNDIRealm logs in to LDAP with the user’s directory name (DN) and the password the user entered, and treats a successful login as an authenticated user (The Realm Component).
LDAP calls this login a bind, and the documentation says JNDIRealm uses a simple bind, which sends the DN and password as they are.
The authentication attribute accepts none, simple, strong, or a provider-specific value such as the name of a SASL mechanism (SASL is a framework for authentication methods used by LDAP and other protocols).
Before the fix, Tomcat removed this setting during the bind that checks the user’s password only when it was GSSAPI, the Kerberos mechanism.
With any other SASL mechanism, the bind ran with that mechanism, and according to the advisory an attacker could authenticate without providing the correct password.
The fix always switches the mechanism to simple for the password-checking bind and restores the configured value afterwards (e43453fc).
Almost every version in the 9.0, 10.1 and 11.0 branches is affected, but the issue only applies when JNDIRealm is in use and authentication is set to a SASL mechanism other than GSSAPI.
To check, look for a <Realm> with org.apache.catalina.realm.JNDIRealm in server.xml or context.xml and see what authentication is set to.
HTTP/2 async request and response mix-up (CVE-2026-101356)
With Servlet async processing, startAsync() releases the thread that received the request, and another thread sends the response after the slow work finishes.
Tomcat recycles its request and response objects. According to the advisory, when an error occurs while an async Servlet is being processed over HTTP/2, Tomcat can recycle and reuse these objects incorrectly, and requests or responses can be mixed up between users.
The fix is one line. When the class that tracks async processing state checks whether it is in an error state, it now treats MUST_ERROR as an error as well as ERROR (1dc6aa15).
The changelog entry in the commit describes it as closing a gap in async error handling that could cause unexpected IllegalStateExceptions for some errors.
Only fairly recent versions are affected: 9.0.118 and later, 10.1.55 and later, and 11.0.22 and later. The issue applies when Tomcat accepts HTTP/2 directly and the application uses async Servlets.
In the default server.xml of 11.0.27, the port 8443 connector that contains Http2Protocol, which enables HTTP/2, is commented out (conf/server.xml).
If a reverse proxy such as nginx accepts HTTP/2 from clients and forwards to Tomcat over HTTP/1.1, Tomcat itself does not process HTTP/2.
AJP response mix-up (CVE-2026-103119)
Apache httpd’s mod_jk and mod_proxy_ajp forward requests to Tomcat using a protocol called AJP.
Servlets can also write output in non-blocking mode: they register a WriteListener and write data only when the socket is ready to send.
According to the advisory, a buffer under-read means that a large non-blocking write over AJP can split the response body between the current request and the next request received on the same connection.
Most likely the second request just fails, but data from the first response may leak into the second.
The fix commit changes how Tomcat closes the response once Content-Length bytes have been written, as the Servlet specification requires (f13748ba).
Before the fix, Tomcat closed the response as soon as the bytes written reached Content-Length.
After the fix, for non-blocking writes only, reaching Content-Length no longer closes the response; it is closed when something tries to write past Content-Length.
The changelog says the change lets a non-blocking write of exactly Content-Length bytes complete in a non-blocking manner before the response is closed.
Affected versions are 11.0.0-M25 to 11.0.26. The 9.x and 10.1.x pages do not list this CVE.
Before 9.0.31, the AJP connector was enabled by default, but the current default server.xml has it commented out.
Tomcat 11 instances not connected to httpd over AJP, and all 9.x and 10.1.x instances, are outside this issue.
Upgrading to the fixed versions
The table lists the fixed release for each branch and the Java version it needs (Apache Tomcat).
| Branch | Fixed version | Required Java |
|---|---|---|
| Tomcat 11.0.x | 11.0.27 | 17 or later |
| Tomcat 10.1.x | 10.1.61 | 11 or later |
| Tomcat 9.0.x | 9.0.123 | 8 or later |
For a standalone Tomcat install, check the current version with bin/version.sh (bin\version.bat on Windows) and replace it with the fixed release from the same branch.
The supported branches are 11.0.x, 10.1.x and 9.0.x. Support for 8.5.x ended on March 31, 2024, and for 10.0.x on October 31, 2022 (Which version do I want?).
End-of-life branches get no fixed release, so anything still on them needs to move to a supported branch.
Applications with embedded Tomcat, such as Spring Boot apps, get their Tomcat version from the framework’s dependency management.
Run mvn dependency:tree or gradle dependencies to see which tomcat-embed-core version is actually on the classpath (Request Smuggling vs. Request Splitting in Spring Boot).
Spring Boot’s dependency management lets you override the Tomcat version with the tomcat.version property (Spring Boot Dependency Versions Properties).