Fully Patched Spring Boot 4 Still Shipped a 9.1 Tomcat CVE — Nothing Warns You
Three weeks after Apache fixed it, the newest Spring Boot 4 release still ships a Tomcat carrying a CVE rated 9.1, and nothing tells you so. Spring Boot 4.1.1 and 4.0.8 manage Tomcat 11.0.24, and CVE-2026–86350 covers 11.0.22 through 11.0.25. If your embedded Tomcat accepts HTTP/2, one request’s headers can get mixed into another’s. Bottom line: don’t wait for 4.1.2; override Tomcat to 11.0.26 now and confirm it in your startup log. In two common build setups, that one-line override is silently ignored.
- Spring Boot
4.1.1and4.0.8, the newest releases as of October 6, 2026, both managetomcat-embed-core 11.0.24. The only Spring Boot that manages the fixed11.0.26is the4.2.0-M2milestone. - CVE-2026–86350 applies only when HTTP/2 reaches Tomcat, but the same
11.0.26release fixed 11 more CVEs, including four in WebSocket handling and one in how HTTP/1.0 requests are processed behind a reverse proxy. - GitHub’s advisory
GHSA-6ff5-mwrj-376mis still unreviewed 13 days after disclosure, so Dependabot raises no alert, and OSV lists no Maven package for this CVE. - In a Maven build that imports
spring-boot-dependenciesas a BOM, and in a Gradle build that usesplatform(), atomcat.versionoverride is ignored, and the build passes while staying on11.0.24. 3.5.16is pinned to10.1.55, and open-source support for 3.5 ended in June. Rolling back to3.5.14avoids this CVE but puts you back under May's CVE-2026-41293.
tomcat-embed-core 11.0.24: what a fully patched Spring Boot 4 app is running
The logging chapter of the official Spring Boot reference includes a sample startup log. These two lines are in it:
o.apache.catalina.core.StandardService : Starting service [Tomcat]
o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/11.0.24]The documentation isn’t out of date. As of October 6, 2026, every Tomcat app that starts on Spring Boot 4.1.1 or 4.0.8 prints exactly this line. Spring Boot pins the Tomcat version through the spring-boot-dependencies BOM. The two releases that shipped on August 20 pin 11.0.24 , and 4.1.0 and 4.0.7, which shipped on June 10, pinned 11.0.22 . Of the Spring Boot 4 GA releases so far, all four from 4.0.7 onward sit inside the affected range.
Put the dates in order and the structure shows. On May 5, Tomcat 11.0.22 fixed a flaw where HTTP/2 request headers were not validated (CVE-2026–41293), and that fix introduced this regression. The report followed on August 28, the 11.0.26 release on September 15, and public disclosure on September 23. Spring Boot moved to Tomcat 11.0.26 in the 4.2.0-M2 milestone on September 24, but no GA release has followed. As of October 6, there is no 4.1.2 on Maven Central.
The build succeeds and startup is clean. Spring Boot doesn’t check the versions it manages against security advisories, so there is no place for a warning to come from. All you get is the startup log printing the version once, at INFO. The more faithfully a team tracks the latest patch, the easier it is to believe that latest means safe, and this time that belief has been wrong for three weeks.
A managed version is a snapshot of the day Spring Boot was released, and a security fix shipped after that day reaches you only if you pull it in yourself.
Spring Boot 3.5 is worse off. 3.5.15 and 3.5.16 manage 10.1.55 , and the affected range on the 10.1 line runs from 10.1.55 to 10.1.59. Open-source support for 3.5 ended on June 30, so no open-source 3.5 release carrying this fix is coming.
CVE-2026–86350 request header mix-up: what crosses over, and when it reaches you
Apache’s advisory explains the flaw in a single sentence: a regression that interprets HTTP/2 requests inconsistently can mix up request headers. The CVE record files it under CWE-444, the HTTP request smuggling family. It carries two ratings. The Tomcat security team rated it Important, and the assessment CISA added to the CVE record scores it CVSS 9.1. The vector behind that 9.1 says confidentiality and integrity can both be badly compromised over the network, with no authentication and no user interaction.
The gap between the two numbers tells you what kind of flaw this is. From Tomcat’s side, it is a regression in how headers are interpreted. From the side of an application that trusts those headers, it is someone else’s request. The public write-ups that dissected this family describe headers crossing between different requests. If the mixed-up header is a value your app uses to decide identity or routing, such as Authorization , a tenant ID, or X-Forwarded-For , the outcome is decided by your code, not by Tomcat. The advisory describes no error path at all. The symptom it describes is the mixed-up header itself.
Apache’s rating measures the flaw and the 9.1 measures an app that trusts the header, so the risk you carry is set by what your code decides from headers.
Exposure has one condition: HTTP/2 has to reach the embedded Tomcat. In Spring Boot, HTTP/2 only works once you turn on server.http2.enabled , and it runs as h2 with TLS or as h2c without it. If a proxy in front terminates HTTP/2 and hands Tomcat HTTP/1.1, Tomcat never has an HTTP/2 request to interpret. So look at what arrives at the connector, not at what the browser speaks. A connector with HTTP/2 enabled over TLS leaves this line at startup:
The ["https-jsse-nio-8443"] connector has been configured to support negotiation to [h2] via ALPNIf you enabled HTTP/2, two more HTTP/2 flaws fixed in the same release apply to you as well: a race condition through recycled request objects that can inject trailer fields into another HTTP/2 request (CVE-2026–77762), and a malformed request that can make another user’s request fail (CVE-2026–78437). Even without HTTP/2, you still need the upgrade. Of the remaining flaws fixed alongside it in 11.0.26, four are in WebSocket handling and one is in how HTTP/1.0 requests are processed behind a reverse proxy.
This is a documented risk, not an observed incident. No public breach or outage report has surfaced yet, and CISA’s assessment as of disclosure day recorded no known exploitation. Exploit trackers, however, have already indexed a repository that claims to be a proof of concept. Genuine or not, once a public PoC is circulating, the patch window for a flaw should be kept short.
GHSA-6ff5-mwrj-376m is unreviewed: why Dependabot and OSV stay quiet
On October 6, 13 days after disclosure, GHSA-6ff5-mwrj-376m is still unreviewed in the GitHub Advisory Database. Its severity reads unknown and its package field is empty. GitHub’s documentation is explicit that unreviewed advisories never produce Dependabot alerts, because nobody has yet checked them for validity or completeness. So Dependabot’s silence isn’t a malfunction. It is working as designed.
OSV is in a similar state. Its record for this CVE lists only Bitnami’s tomcat package, with no Maven coordinates such as org.apache.tomcat.embed:tomcat-embed-core . By HeroDevs' count on September 24, only 3 of the 23 September Tomcat CVEs had records reviewed down to package ranges.
You can check GitHub’s side yourself with this command:
#bash
curl -s https://api.github.com/advisories/GHSA-6ff5-mwrj-376m | jq '.type, (.vulnerabilities | length)'Until type turns into reviewed and vulnerabilities is populated, Dependabot will not alert on this CVE. Tools that match on NVD CPEs, and commercial scanners with their own databases, may behave differently. You can only read your scanner's green light once you know which data it reads.
In the first weeks after a disclosure, a green scanner doesn’t mean you are safe; it means the data hasn’t arrived yet.
tomcat.version is ignored: the override that never reaches your build
Everyone knows the fix: set tomcat.version to 11.0.26 . In a Maven build that uses spring-boot-starter-parent as its parent, that works exactly as written. The problem is that plenty of builds aren't set up that way.
Organizations with a shared corporate parent POM can’t use the Spring Boot parent, so they import spring-boot-dependencies as a BOM. In that setup, the property changes nothing. The Spring Boot Maven plugin documentation states outright that this approach doesn't let you override individual dependencies through properties.
<!--xml-->
<properties>
<tomcat.version>11.0.26</tomcat.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>4.1.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>Maven doesn’t warn about a property nobody reads. The build succeeds, and the dependency tree still says 11.0.24 . The only trace of the fix is a commit message claiming CVE-2026-86350 was handled.
Gradle is the same. With the io.spring.dependency-management plugin, tomcat.version takes effect. But if you bring in the Spring Boot BOM through Gradle's native BOM support, that is, with platform() , the Spring Boot Gradle plugin documentation is plain that the properties from spring-boot-dependencies cannot control the versions it manages. A tomcat.version written in gradle.properties is no different.
Even when the override works, one trap remains. That line keeps Tomcat pinned to 11.0.26 after Spring Boot starts managing 11.0.26 or later. When the next Tomcat security release ships and Spring Boot picks it up, your build stays on the number you wrote today, just as silently as this time.
Get HobbiesPark’s stories in your inbox
Join Medium for free to get updates from this writer.
An override is done not when you write it, but when you see the version change in your startup log.
The fix: override Tomcat the way your build actually reads it
The judgment first: don’t wait for Spring Boot 4.1.2. The fixed Tomcat has been out for three weeks, the override takes a few lines, and when the next Spring Boot patch ships is not up to you.
See what is running now.
#bash
./mvnw dependency:tree -Dincludes=org.apache.tomcat.embed
./gradlew dependencyInsight --dependency tomcat-embed-core --configuration runtimeClasspath
grep "Starting Servlet engine" app.logIf you see 11.0.22 through 11.0.25, or 10.1.55 through 10.1.59, you are affected.
Upgrade it the way your build reads versions. With spring-boot-starter-parent , one property is enough. On Spring Boot 3.5, put 10.1.60 in the same place.
<!--xml-->
<properties>
<tomcat.version>11.0.26</tomcat.version>
</properties>If you import the BOM, declare the versions yourself ahead of the spring-boot-dependencies import, as the Spring Boot documentation recommends.
<!--xml-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>11.0.26</version>
</dependency>
<!-- repeat for every org.apache.tomcat.embed artifact in your tree -->
<!-- the spring-boot-dependencies import goes after these entries -->
</dependencies>
</dependencyManagement>In Gradle, it depends on how you bring in the BOM:
//kotlin
// with the io.spring.dependency-management plugin
extra["tomcat.version"] = "11.0.26"
// with platform(SpringBootPlugin.BOM_COORDINATES) instead
configurations.all {
resolutionStrategy.eachDependency {
if (requested.group == "org.apache.tomcat.embed") {
useVersion("11.0.26")
}
}
}Confirm it in the startup log. You aren’t done until it prints Starting Servlet engine: [Apache Tomcat/11.0.26] .
If you can’t change the build today. If the fix will take days to deploy and HTTP/2 reaches Tomcat in the meantime, switching HTTP/2 off for a while with server.http2.enabled=false is an option. Keep in mind that the only mitigation Apache's advisory offers is the upgrade, and turning off HTTP/2 closes only the three HTTP/2 flaws while the other nine stay open.
On 3.5, don’t roll back. Dropping to 3.5.14 gives you Tomcat 10.1.54 . That version avoids this CVE, but it sits inside the range of May's CVE-2026-41293 and inside the ranges of at least nine of the CVEs disclosed in September. The job on 3.5 is to override to 10.1.60 , and to put on the schedule the fact that this line will get no more open-source fixes.
Give the override an expiry condition. When Spring Boot ships a release that manages 11.0.26 or later, delete the line. Leave this CVE number in a comment next to the override, so whoever reads that line later can tell whether it is safe to remove.
Versions checked against
Version data was checked on October 6, 2026, against the spring-boot-dependencies POMs published on Maven Central (3.5.14, 3.5.15, 3.5.16, 4.0.7, 4.0.8, 4.1.0, 4.1.1 and 4.2.0-M2), the Apache Tomcat security pages, the CVE record and the GitHub advisory page. No exploit was run.
More in this series
From the Spring Boot 4 Production Traps series:
I Upgraded to Spring Boot 4 — My Health Checks Lied for Nine Days
https://medium.com/javarevisited/spring-boot-4-actuator-health-missing-0f62aaf7fad1
I Upgraded to Gradle 9 — My Integration Tests Stopped Running and CI Stayed Green
https://medium.com/javarevisited/gradle-9-custom-test-task-no-source-8c86749a121a
If this saved you a scramble
If this cut your team’s response time, clap so it reaches the next person, follow the series, repost it to whoever owns security response, and subscribe to get the next one by email.
Sources
Apache Tomcat 11 security vulnerabilities
https://tomcat.apache.org/security-11.html
Apache Tomcat 10 security vulnerabilities
https://tomcat.apache.org/security-10.html
Apache Tomcat security announcement for CVE-2026–86350 (users list, updated September 28)
http://www.mail-archive.com/users@tomcat.apache.org/msg146228.html
CVE-2026–86350 record
https://www.cve.org/CVERecord?id=CVE-2026-86350
GitHub Advisory GHSA-6ff5-mwrj-376m
https://github.com/advisories/GHSA-6ff5-mwrj-376m
GitHub Docs, About the GitHub Advisory database
https://docs.github.com/en/code-security/security-advisories/working-with-global-security-advisories-from-the-github-advisory-database/about-the-github-advisory-database
OSV, CVE-2026–86350
https://osv.dev/vulnerability/CVE-2026-86350
Spring Boot reference, Logging
https://docs.spring.io/spring-boot/reference/features/logging.html
Spring Boot how-to, Embedded Web Servers
https://docs.spring.io/spring-boot/how-to/webserver.html
Spring Boot Maven Plugin, Using the Plugin
https://docs.spring.io/spring-boot/maven-plugin/using.html
Spring Boot Gradle Plugin, Managing Dependencies
https://docs.spring.io/spring-boot/gradle-plugin/managing-dependencies.html
spring-boot-dependencies on Maven Central
https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-dependencies/
Spring Boot support dates
https://endoflife.date/spring-boot
HeroDevs, Spring Boot managed dependencies still get CVEs after EOL
https://www.herodevs.com/blog-posts/spring-boot-managed-dependencies-still-get-cves-after-eol-september-2026-patch-round-up
CVE-2026–77762 and the HTTP/2 request-mixup family in Apache Tomcat
https://dev.to/kozhevniko/cve-2026-77762-and-the-http2-request-mixup-family-in-apache-tomcat-28c3










