Apache Tomcat: Trailer header parsing too lenient
Description
Improper Input Validation vulnerability in Apache Tomcat.Tomcat from 11.0.0-M1 through 11.0.0-M11, from 10.1.0-M1 through 10.1.13, from 9.0.0-M1 through 9.0.81 and from 8.5.0 through 8.5.93 did not correctly parse HTTP trailer headers. A specially crafted, invalid trailer header could cause Tomcat to treat a single request as multiple requests leading to the possibility of request smuggling when behind a reverse proxy.
Older, EOL versions may also be affected.
Users are recommended to upgrade to version 11.0.0-M12 onwards, 10.1.14 onwards, 9.0.81 onwards or 8.5.94 onwards, which fix the issue.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Improper validation of HTTP trailer headers in Apache Tomcat allows request smuggling when behind a reverse proxy, affecting multiple versions.
Vulnerability
Details
CVE-2023-45648 is an improper input validation vulnerability in Apache Tomcat's handling of HTTP trailer headers. The flaw exists in the parseHeader() methods of Http11InputBuffer and ChunkedInputFilter, which did not correctly validate trailer headers [1][2][3][4]. A specially crafted, invalid trailer header can cause Tomcat to misinterpret a single HTTP request as multiple requests, leading to request smuggling [1].
Exploitation
An attacker can exploit this issue by sending a malicious HTTP request with a crafted trailer header to a Tomcat instance that is behind a reverse proxy. No authentication is required to trigger the vulnerability. The improper parsing logic, fixed by inverting a condition check (moving the check for chr != Constants.HT after isControl()), allows control characters other than horizontal tab to be interpreted incorrectly, enabling request splitting [2][3][4].
Impact
Successful exploitation could allow an attacker to perform HTTP request smuggling attacks. This can lead to security bypass, cache poisoning, credential theft, and session hijacking, depending on the proxy configuration and application logic [1].
Mitigation
Users should upgrade to Apache Tomcat versions 11.0.0-M12, 10.1.14, 9.0.81, or 8.5.94, which contain the fix. Older, end-of-life versions may also be affected and should be upgraded or decommissioned [1].
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.apache.tomcat:tomcatMaven | >= 11.0.0-M1, < 11.0.0-M12 | 11.0.0-M12 |
org.apache.tomcat:tomcatMaven | >= 10.1.0-M1, < 10.1.14 | 10.1.14 |
org.apache.tomcat:tomcatMaven | >= 9.0.0-M1, < 9.0.81 | 9.0.81 |
org.apache.tomcat:tomcatMaven | >= 8.5.0, < 8.5.94 | 8.5.94 |
org.apache.tomcat.embed:tomcat-embed-coreMaven | >= 11.0.0-M1, < 11.0.0-M12 | 11.0.0-M12 |
org.apache.tomcat.embed:tomcat-embed-coreMaven | >= 10.1.0-M1, < 10.1.14 | 10.1.14 |
org.apache.tomcat.embed:tomcat-embed-coreMaven | >= 9.0.0-M1, < 9.0.81 | 9.0.81 |
org.apache.tomcat.embed:tomcat-embed-coreMaven | >= 8.5.0, < 8.5.94 | 8.5.94 |
Affected products
32- osv-coords31 versionspkg:bitnami/tomcatpkg:maven/org.apache.tomcat.embed/tomcat-embed-corepkg:maven/org.apache.tomcat/tomcatpkg:rpm/almalinux/tomcatpkg:rpm/almalinux/tomcat-admin-webappspkg:rpm/almalinux/tomcat-docs-webapppkg:rpm/almalinux/tomcat-el-3.0-apipkg:rpm/almalinux/tomcat-jsp-2.3-apipkg:rpm/almalinux/tomcat-libpkg:rpm/almalinux/tomcat-servlet-4.0-apipkg:rpm/almalinux/tomcat-webappspkg:rpm/opensuse/tomcat&distro=openSUSE%20Leap%2015.5pkg:rpm/opensuse/tomcat&distro=openSUSE%20Tumbleweedpkg:rpm/suse/tomcat&distro=SUSE%20Enterprise%20Storage%207.1pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP1-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP2-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP3-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP4-ESPOSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP4-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Web%20and%20Scripting%2015%20SP5pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%2012%20SP5pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP1-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP2-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP3-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP4-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2012%20SP5pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP1pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP2pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP3pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP4pkg:rpm/suse/tomcat&distro=SUSE%20Manager%20Server%204.3
>= 8.5.0, < 8.5.94+ 30 more
- (no CPE)range: >= 8.5.0, < 8.5.94
- (no CPE)range: >= 11.0.0-M1, < 11.0.0-M12
- (no CPE)range: >= 11.0.0-M1, < 11.0.0-M12
- (no CPE)range: < 1:9.0.62-27.el8_9.2
- (no CPE)range: < 1:9.0.62-27.el8_9.2
- (no CPE)range: < 1:9.0.62-27.el8_9.2
- (no CPE)range: < 1:9.0.62-27.el8_9.2
- (no CPE)range: < 1:9.0.62-27.el8_9.2
- (no CPE)range: < 1:9.0.62-27.el8_9.2
- (no CPE)range: < 1:9.0.62-27.el8_9.2
- (no CPE)range: < 1:9.0.62-27.el8_9.2
- (no CPE)range: < 9.0.85-150200.57.1
- (no CPE)range: < 9.0.82-2.1
- (no CPE)range: < 9.0.85-150200.57.1
- (no CPE)range: < 9.0.36-150100.4.98.1
- (no CPE)range: < 9.0.85-150200.57.1
- (no CPE)range: < 9.0.85-150200.57.1
- (no CPE)range: < 9.0.85-150200.57.1
- (no CPE)range: < 9.0.85-150200.57.1
- (no CPE)range: < 9.0.85-150200.57.1
- (no CPE)range: < 9.0.36-3.111.1
- (no CPE)range: < 9.0.36-150100.4.98.1
- (no CPE)range: < 9.0.85-150200.57.1
- (no CPE)range: < 9.0.85-150200.57.1
- (no CPE)range: < 9.0.85-150200.57.1
- (no CPE)range: < 9.0.36-3.111.1
- (no CPE)range: < 9.0.36-150100.4.98.1
- (no CPE)range: < 9.0.85-150200.57.1
- (no CPE)range: < 9.0.85-150200.57.1
- (no CPE)range: < 9.0.85-150200.57.1
- (no CPE)range: < 9.0.85-150200.57.1
- Apache Software Foundation/Apache Tomcatv5Range: 11.0.0-M1
Patches
4c83fe47725f7Align processing of trailer headers with standard processing
4 files changed · +26 −2
java/org/apache/coyote/http11/filters/ChunkedInputFilter.java+14 −1 modified@@ -31,6 +31,7 @@ import org.apache.tomcat.util.buf.HexUtils; import org.apache.tomcat.util.buf.MessageBytes; import org.apache.tomcat.util.http.MimeHeaders; +import org.apache.tomcat.util.http.parser.HttpParser; import org.apache.tomcat.util.net.ApplicationBufferHandler; import org.apache.tomcat.util.res.StringManager; @@ -503,6 +504,13 @@ protected void parseEndChunk() throws IOException { private boolean parseHeader() throws IOException { + /* + * Implementation note: Any changes to this method probably need to be echoed in + * Http11InputBuffer.parseHeader(). Why not use a common implementation? In short, this code uses blocking + * reads whereas Http11InputBuffer using non-blocking reads. The code is just different enough that a common + * implementation wasn't viewed as practical. + */ + MimeHeaders headers = request.getMimeHeaders(); byte chr = 0; @@ -549,6 +557,9 @@ private boolean parseHeader() throws IOException { if (chr == Constants.COLON) { colon = true; + } else if (!HttpParser.isToken(chr)) { + // Non-token characters are illegal in header names + throw new IOException(sm.getString("chunkedInputFilter.invalidTrailerHeaderName")); } else { trailingHeaders.append(chr); } @@ -610,7 +621,9 @@ private boolean parseHeader() throws IOException { if (chr == Constants.CR || chr == Constants.LF) { parseCRLF(true); eol = true; - } else if (chr == Constants.SP) { + } else if (HttpParser.isControl(chr) && chr != Constants.HT) { + throw new IOException(sm.getString("chunkedInputFilter.invalidTrailerHeaderValue")); + } else if (chr == Constants.SP || chr == Constants.HT) { trailingHeaders.append(chr); } else { trailingHeaders.append(chr);
java/org/apache/coyote/http11/filters/LocalStrings.properties+2 −0 modified@@ -24,6 +24,8 @@ chunkedInputFilter.invalidCrlfCRCR=Invalid end of line sequence (CRCR) chunkedInputFilter.invalidCrlfNoCR=Invalid end of line sequence (No CR before LF) chunkedInputFilter.invalidCrlfNoData=Invalid end of line sequence (no data available to read) chunkedInputFilter.invalidHeader=Invalid chunk header +chunkedInputFilter.invalidTrailerHeaderName=Invalid trailer header name (non-token character in name) +chunkedInputFilter.invalidTrailerHeaderValue=Invalid trailer header value (control character in value) chunkedInputFilter.maxExtension=maxExtensionSize exceeded chunkedInputFilter.maxTrailer=maxTrailerSize exceeded
java/org/apache/coyote/http11/Http11InputBuffer.java+7 −1 modified@@ -830,6 +830,12 @@ private boolean fill(boolean block) throws IOException { */ private HeaderParseStatus parseHeader() throws IOException { + /* + * Implementation note: Any changes to this method probably need to be echoed in + * ChunkedInputFilter.parseHeader(). Why not use a common implementation? In short, this code uses non-blocking + * reads whereas ChunkedInputFilter using blocking reads. The code is just different enough that a common + * implementation wasn't viewed as practical. + */ while (headerParsePos == HeaderParsePosition.HEADER_START) { // Read new bytes if needed @@ -972,7 +978,7 @@ private HeaderParseStatus parseHeader() throws IOException { } else if (prevChr == Constants.CR) { // Invalid value - also need to delete header return skipLine(true); - } else if (chr != Constants.HT && HttpParser.isControl(chr)) { + } else if (HttpParser.isControl(chr) && chr != Constants.HT) { // Invalid value - also need to delete header return skipLine(true); } else if (chr == Constants.SP || chr == Constants.HT) {
webapps/docs/changelog.xml+3 −0 modified@@ -156,6 +156,9 @@ <fix> Avoid rare thread safety issue accessing message digest map. (remm) </fix> + <fix> + Align validation of HTTP trailer fields with standard fields. (markt) + </fix> </changelog> </subsection> <subsection name="Jasper">
8ecff306507bAlign processing of trailer headers with standard processing
4 files changed · +26 −2
java/org/apache/coyote/http11/filters/ChunkedInputFilter.java+14 −1 modified@@ -30,6 +30,7 @@ import org.apache.coyote.http11.InputFilter; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.buf.HexUtils; +import org.apache.tomcat.util.http.parser.HttpParser; import org.apache.tomcat.util.net.ApplicationBufferHandler; import org.apache.tomcat.util.res.StringManager; @@ -443,6 +444,13 @@ protected void parseEndChunk() throws IOException { private boolean parseHeader() throws IOException { + /* + * Implementation note: Any changes to this method probably need to be echoed in + * Http11InputBuffer.parseHeader(). Why not use a common implementation? In short, this code uses blocking + * reads whereas Http11InputBuffer using non-blocking reads. The code is just different enough that a common + * implementation wasn't viewed as practical. + */ + Map<String,String> headers = request.getTrailerFields(); byte chr = 0; @@ -489,6 +497,9 @@ private boolean parseHeader() throws IOException { if (chr == Constants.COLON) { colon = true; + } else if (!HttpParser.isToken(chr)) { + // Non-token characters are illegal in header names + throw new IOException(sm.getString("chunkedInputFilter.invalidTrailerHeaderName")); } else { trailingHeaders.append(chr); } @@ -550,7 +561,9 @@ private boolean parseHeader() throws IOException { if (chr == Constants.CR || chr == Constants.LF) { parseCRLF(true); eol = true; - } else if (chr == Constants.SP) { + } else if (HttpParser.isControl(chr) && chr != Constants.HT) { + throw new IOException(sm.getString("chunkedInputFilter.invalidTrailerHeaderValue")); + } else if (chr == Constants.SP || chr == Constants.HT) { trailingHeaders.append(chr); } else { trailingHeaders.append(chr);
java/org/apache/coyote/http11/filters/LocalStrings.properties+2 −0 modified@@ -24,6 +24,8 @@ chunkedInputFilter.invalidCrlfCRCR=Invalid end of line sequence (CRCR) chunkedInputFilter.invalidCrlfNoCR=Invalid end of line sequence (No CR before LF) chunkedInputFilter.invalidCrlfNoData=Invalid end of line sequence (no data available to read) chunkedInputFilter.invalidHeader=Invalid chunk header +chunkedInputFilter.invalidTrailerHeaderName=Invalid trailer header name (non-token character in name) +chunkedInputFilter.invalidTrailerHeaderValue=Invalid trailer header value (control character in value) chunkedInputFilter.maxExtension=maxExtensionSize exceeded chunkedInputFilter.maxTrailer=maxTrailerSize exceeded
java/org/apache/coyote/http11/Http11InputBuffer.java+7 −1 modified@@ -830,6 +830,12 @@ private boolean fill(boolean block) throws IOException { */ private HeaderParseStatus parseHeader() throws IOException { + /* + * Implementation note: Any changes to this method probably need to be echoed in + * ChunkedInputFilter.parseHeader(). Why not use a common implementation? In short, this code uses non-blocking + * reads whereas ChunkedInputFilter using blocking reads. The code is just different enough that a common + * implementation wasn't viewed as practical. + */ while (headerParsePos == HeaderParsePosition.HEADER_START) { // Read new bytes if needed @@ -972,7 +978,7 @@ private HeaderParseStatus parseHeader() throws IOException { } else if (prevChr == Constants.CR) { // Invalid value - also need to delete header return skipLine(true); - } else if (chr != Constants.HT && HttpParser.isControl(chr)) { + } else if (HttpParser.isControl(chr) && chr != Constants.HT) { // Invalid value - also need to delete header return skipLine(true); } else if (chr == Constants.SP || chr == Constants.HT) {
webapps/docs/changelog.xml+3 −0 modified@@ -160,6 +160,9 @@ Improve statistics collection for upgraded connections under load. (remm) </fix> + <fix> + Align validation of HTTP trailer fields with standard fields. (markt) + </fix> </changelog> </subsection> <subsection name="Jasper">
eb5c094e5560Align processing of trailer headers with standard processing
4 files changed · +26 −2
java/org/apache/coyote/http11/filters/ChunkedInputFilter.java+14 −1 modified@@ -30,6 +30,7 @@ import org.apache.coyote.http11.InputFilter; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.buf.HexUtils; +import org.apache.tomcat.util.http.parser.HttpParser; import org.apache.tomcat.util.net.ApplicationBufferHandler; import org.apache.tomcat.util.res.StringManager; @@ -443,6 +444,13 @@ protected void parseEndChunk() throws IOException { private boolean parseHeader() throws IOException { + /* + * Implementation note: Any changes to this method probably need to be echoed in + * Http11InputBuffer.parseHeader(). Why not use a common implementation? In short, this code uses blocking + * reads whereas Http11InputBuffer using non-blocking reads. The code is just different enough that a common + * implementation wasn't viewed as practical. + */ + Map<String,String> headers = request.getTrailerFields(); byte chr = 0; @@ -489,6 +497,9 @@ private boolean parseHeader() throws IOException { if (chr == Constants.COLON) { colon = true; + } else if (!HttpParser.isToken(chr)) { + // Non-token characters are illegal in header names + throw new IOException(sm.getString("chunkedInputFilter.invalidTrailerHeaderName")); } else { trailingHeaders.append(chr); } @@ -550,7 +561,9 @@ private boolean parseHeader() throws IOException { if (chr == Constants.CR || chr == Constants.LF) { parseCRLF(true); eol = true; - } else if (chr == Constants.SP) { + } else if (HttpParser.isControl(chr) && chr != Constants.HT) { + throw new IOException(sm.getString("chunkedInputFilter.invalidTrailerHeaderValue")); + } else if (chr == Constants.SP || chr == Constants.HT) { trailingHeaders.append(chr); } else { trailingHeaders.append(chr);
java/org/apache/coyote/http11/filters/LocalStrings.properties+2 −0 modified@@ -24,6 +24,8 @@ chunkedInputFilter.invalidCrlfCRCR=Invalid end of line sequence (CRCR) chunkedInputFilter.invalidCrlfNoCR=Invalid end of line sequence (No CR before LF) chunkedInputFilter.invalidCrlfNoData=Invalid end of line sequence (no data available to read) chunkedInputFilter.invalidHeader=Invalid chunk header +chunkedInputFilter.invalidTrailerHeaderName=Invalid trailer header name (non-token character in name) +chunkedInputFilter.invalidTrailerHeaderValue=Invalid trailer header value (control character in value) chunkedInputFilter.maxExtension=maxExtensionSize exceeded chunkedInputFilter.maxTrailer=maxTrailerSize exceeded
java/org/apache/coyote/http11/Http11InputBuffer.java+7 −1 modified@@ -826,6 +826,12 @@ private boolean fill(boolean block) throws IOException { */ private HeaderParseStatus parseHeader() throws IOException { + /* + * Implementation note: Any changes to this method probably need to be echoed in + * ChunkedInputFilter.parseHeader(). Why not use a common implementation? In short, this code uses non-blocking + * reads whereas ChunkedInputFilter using blocking reads. The code is just different enough that a common + * implementation wasn't viewed as practical. + */ while (headerParsePos == HeaderParsePosition.HEADER_START) { // Read new bytes if needed @@ -968,7 +974,7 @@ private HeaderParseStatus parseHeader() throws IOException { } else if (prevChr == Constants.CR) { // Invalid value - also need to delete header return skipLine(); - } else if (chr != Constants.HT && HttpParser.isControl(chr)) { + } else if (HttpParser.isControl(chr) && chr != Constants.HT) { // Invalid value - also need to delete header return skipLine(); } else if (chr == Constants.SP || chr == Constants.HT) {
webapps/docs/changelog.xml+3 −0 modified@@ -170,6 +170,9 @@ <code>newPushBuilder()</code> will always return <code>null</code>. (markt) </update> + <fix> + Align validation of HTTP trailer fields with standard fields. (markt) + </fix> </changelog> </subsection> <subsection name="Jasper">
59583245639dAlign processing of trailer headers with standard processing
4 files changed · +26 −2
java/org/apache/coyote/http11/filters/ChunkedInputFilter.java+14 −1 modified@@ -30,6 +30,7 @@ import org.apache.coyote.http11.InputFilter; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.buf.HexUtils; +import org.apache.tomcat.util.http.parser.HttpParser; import org.apache.tomcat.util.net.ApplicationBufferHandler; import org.apache.tomcat.util.res.StringManager; @@ -443,6 +444,13 @@ protected void parseEndChunk() throws IOException { private boolean parseHeader() throws IOException { + /* + * Implementation note: Any changes to this method probably need to be echoed in + * Http11InputBuffer.parseHeader(). Why not use a common implementation? In short, this code uses blocking + * reads whereas Http11InputBuffer using non-blocking reads. The code is just different enough that a common + * implementation wasn't viewed as practical. + */ + Map<String,String> headers = request.getTrailerFields(); byte chr = 0; @@ -489,6 +497,9 @@ private boolean parseHeader() throws IOException { if (chr == Constants.COLON) { colon = true; + } else if (!HttpParser.isToken(chr)) { + // Non-token characters are illegal in header names + throw new IOException(sm.getString("chunkedInputFilter.invalidTrailerHeaderName")); } else { trailingHeaders.append(chr); } @@ -550,7 +561,9 @@ private boolean parseHeader() throws IOException { if (chr == Constants.CR || chr == Constants.LF) { parseCRLF(true); eol = true; - } else if (chr == Constants.SP) { + } else if (HttpParser.isControl(chr) && chr != Constants.HT) { + throw new IOException(sm.getString("chunkedInputFilter.invalidTrailerHeaderValue")); + } else if (chr == Constants.SP || chr == Constants.HT) { trailingHeaders.append(chr); } else { trailingHeaders.append(chr);
java/org/apache/coyote/http11/filters/LocalStrings.properties+2 −0 modified@@ -24,6 +24,8 @@ chunkedInputFilter.invalidCrlfCRCR=Invalid end of line sequence (CRCR) chunkedInputFilter.invalidCrlfNoCR=Invalid end of line sequence (No CR before LF) chunkedInputFilter.invalidCrlfNoData=Invalid end of line sequence (no data available to read) chunkedInputFilter.invalidHeader=Invalid chunk header +chunkedInputFilter.invalidTrailerHeaderName=Invalid trailer header name (non-token character in name) +chunkedInputFilter.invalidTrailerHeaderValue=Invalid trailer header value (control character in value) chunkedInputFilter.maxExtension=maxExtensionSize exceeded chunkedInputFilter.maxTrailer=maxTrailerSize exceeded
java/org/apache/coyote/http11/Http11InputBuffer.java+7 −1 modified@@ -830,6 +830,12 @@ private boolean fill(boolean block) throws IOException { */ private HeaderParseStatus parseHeader() throws IOException { + /* + * Implementation note: Any changes to this method probably need to be echoed in + * ChunkedInputFilter.parseHeader(). Why not use a common implementation? In short, this code uses non-blocking + * reads whereas ChunkedInputFilter using blocking reads. The code is just different enough that a common + * implementation wasn't viewed as practical. + */ while (headerParsePos == HeaderParsePosition.HEADER_START) { // Read new bytes if needed @@ -972,7 +978,7 @@ private HeaderParseStatus parseHeader() throws IOException { } else if (prevChr == Constants.CR) { // Invalid value - also need to delete header return skipLine(true); - } else if (chr != Constants.HT && HttpParser.isControl(chr)) { + } else if (HttpParser.isControl(chr) && chr != Constants.HT) { // Invalid value - also need to delete header return skipLine(true); } else if (chr == Constants.SP || chr == Constants.HT) {
webapps/docs/changelog.xml+3 −0 modified@@ -160,6 +160,9 @@ Improve statistics collection for upgraded connections under load. (remm) </fix> + <fix> + Align validation of HTTP trailer fields with standard fields. (markt) + </fix> </changelog> </subsection> <subsection name="Jasper">
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
12- github.com/advisories/GHSA-r6j3-px5g-cq3xghsaADVISORY
- lists.apache.org/thread/2pv8yz1pyp088tsxfb7ogltk9msk0jdpghsavendor-advisoryWEB
- nvd.nist.gov/vuln/detail/CVE-2023-45648ghsaADVISORY
- www.openwall.com/lists/oss-security/2023/10/10/10ghsaWEB
- github.com/apache/tomcat/commit/59583245639d8c42ae0009f4a4a70464d3ea70a0ghsaWEB
- github.com/apache/tomcat/commit/8ecff306507be8e4fd3adee1ae5de1ea6661a8f4ghsaWEB
- github.com/apache/tomcat/commit/c83fe47725f7ae9ae213568d9039171124fb7ec6ghsaWEB
- github.com/apache/tomcat/commit/eb5c094e5560764cda436362254997511a3ca1f6ghsaWEB
- lists.debian.org/debian-lts-announce/2023/10/msg00020.htmlghsaWEB
- security.netapp.com/advisory/ntap-20231103-0007ghsaWEB
- www.debian.org/security/2023/dsa-5521ghsaWEB
- www.debian.org/security/2023/dsa-5522ghsaWEB
News mentions
0No linked articles in our index yet.