CVE-2013-4286
Description
Apache Tomcat improperly handles inconsistent HTTP headers, allowing request smuggling attacks via multiple Content-Length or chunked encoding.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Apache Tomcat improperly handles inconsistent HTTP headers, allowing request smuggling attacks via multiple Content-Length or chunked encoding.
Vulnerability
Apache Tomcat versions before 6.0.39, 7.x before 7.0.47, and 8.x before 8.0.0-RC3 fail to properly handle inconsistent HTTP request headers when an HTTP or AJP connector is used [1][2]. This is an incomplete fix for CVE-2005-2090. The vulnerability allows remote attackers to trigger incorrect identification of a request's length by sending either multiple Content-Length headers or a Content-Length header combined with a Transfer-Encoding: chunked header [4].
Exploitation
An attacker with network access to the Tomcat server can send a crafted HTTP request containing inconsistent headers. No authentication is required. The server misinterprets the request boundary, enabling request smuggling. For example, sending a request with both a Content-Length and Transfer-Encoding: chunked header causes the server to process the request body incorrectly, allowing the attacker to inject a second request that may be interpreted as a separate request by a downstream proxy or cache [4].
Impact
Successful exploitation can lead to web cache poisoning, cross-site scripting (XSS) attacks, or disclosure of sensitive information from other requests. The attacker gains the ability to manipulate or intercept other users' requests and responses, potentially compromising data confidentiality and integrity [4].
Mitigation
Fixed versions are Apache Tomcat 6.0.39, 7.0.47, and 8.0.0-RC3 [1][2]. Red Hat provided updates via RHSA-2014-0686 for RHEL 7 (tomcat-7.0.42-5.el7_0) and RHSA-2014-0343 for JBoss EAP 6.2.2 [3][4]. Note that Tomcat 7.0.x and 8.0.x have reached end of life and are no longer supported; users should upgrade to Tomcat 9.0.x or later to obtain security fixes [1][2]. No workarounds are documented.
AI Insight generated on May 23, 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 | < 6.0.39 | 6.0.39 |
org.apache.tomcat:tomcatMaven | >= 7.0.0, < 7.0.47 | 7.0.47 |
org.apache.tomcat:tomcatMaven | >= 8.0.0-RC1, < 8.0.0-RC3 | 8.0.0-RC3 |
Affected products
184cpe:2.3:a:apache:tomcat:*:*:*:*:*:*:*:*+ 182 more
- cpe:2.3:a:apache:tomcat:*:*:*:*:*:*:*:*range: <=6.0.37
- cpe:2.3:a:apache:tomcat:1.1.3:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:3.0:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:3.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:3.1.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:3.2:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:3.2.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:3.2.2:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:3.2.2:beta2:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:3.2.3:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:3.2.4:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:3.3:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:3.3.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:3.3.1a:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:3.3.2:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.0.0:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.0.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.0.2:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.0.3:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.0.4:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.0.5:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.0.6:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.1.0:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.1.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.1.10:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.1.12:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.1.15:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.1.2:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.1.24:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.1.28:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.1.29:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.1.3:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.1.31:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.1.36:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.1.3:beta:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:4.1.9:beta:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.0:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.10:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.11:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.12:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.13:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.14:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.15:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.16:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.17:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.18:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.19:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.2:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.21:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.22:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.23:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.24:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.25:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.26:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.27:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.28:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.29:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.3:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.30:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.4:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.5:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.6:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.7:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.8:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.0.9:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.0:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.10:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.11:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.12:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.13:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.14:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.15:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.16:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.17:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.18:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.19:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.2:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.20:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.21:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.22:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.23:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.24:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.25:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.26:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.27:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.28:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.29:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.3:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.30:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.31:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.32:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.33:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.34:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.35:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.4:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.5:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.6:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.7:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.8:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:5.5.9:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.0:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.0:alpha:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.10:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.11:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.12:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.13:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.14:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.15:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.16:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.17:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.18:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.19:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.1:alpha:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.2:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.20:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.24:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.26:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.27:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.28:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.29:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.2:alpha:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.2:beta:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.3:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.30:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.31:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.32:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.33:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.35:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:6.0.36:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.0:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.0:beta:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.10:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.11:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.12:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.13:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.14:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.15:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.16:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.17:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.18:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.19:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.2:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.20:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.21:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.22:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.23:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.24:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.25:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.26:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.27:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.28:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.29:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.2:beta:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.3:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.30:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.31:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.32:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.33:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.34:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.35:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.36:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.37:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.38:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.39:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.4:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.40:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.41:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.42:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.43:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.44:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.45:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.46:*:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:7.0.4:beta:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:8.0.0:rc1:*:*:*:*:*:*
- cpe:2.3:a:apache:tomcat:8.0.0:rc2:*:*:*:*:*:*
Patches
541b90b6ebc3eBetter adherence to RFC2616 for content-length headers
4 files changed · +102 −15
java/org/apache/coyote/ajp/AbstractAjpProcessor.java+12 −2 modified@@ -25,6 +25,8 @@ import java.security.cert.X509Certificate; import java.util.concurrent.atomic.AtomicBoolean; +import javax.servlet.http.HttpServletResponse; + import org.apache.coyote.AbstractProcessor; import org.apache.coyote.ActionCode; import org.apache.coyote.AsyncContextCallback; @@ -691,6 +693,7 @@ protected void prepareRequest() { // Set this every time in case limit has been changed via JMX headers.setLimit(endpoint.getMaxHeaderCount()); + boolean contentLengthSet = false; int hCount = requestHeaderMessage.getInt(); for(int i = 0 ; i < hCount ; i++) { String hName = null; @@ -725,8 +728,15 @@ protected void prepareRequest() { if (hId == Constants.SC_REQ_CONTENT_LENGTH || (hId == -1 && tmpMB.equalsIgnoreCase("Content-Length"))) { - // just read the content-length header, so set it - request.setContentLength(vMB.getLong()); + long cl = vMB.getLong(); + if (contentLengthSet) { + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + error = true; + } else { + contentLengthSet = true; + // Set the content-length header for the request + request.setContentLength(cl); + } } else if (hId == Constants.SC_REQ_CONTENT_TYPE || (hId == -1 && tmpMB.equalsIgnoreCase("Content-Type"))) { // just read the content-type header, so set it
java/org/apache/coyote/http11/AbstractHttp11Processor.java+14 −4 modified@@ -1296,10 +1296,20 @@ protected void prepareRequest() { // Parse content-length header long contentLength = request.getContentLengthLong(); - if (contentLength >= 0 && !contentDelimitation) { - getInputBuffer().addActiveFilter - (inputFilters[Constants.IDENTITY_FILTER]); - contentDelimitation = true; + if (contentLength >= 0) { + if (contentDelimitation) { + // contentDelimitation being true at this point indicates that + // chunked encoding is being used but chunked encoding should + // not be used with a content length. RFC 2616, section 4.4, + // bullet 3 states Content-Length must be ignored in this case - + // so remove it. + headers.removeHeader("content-length"); + request.setContentLength(-1); + } else { + getInputBuffer().addActiveFilter + (inputFilters[Constants.IDENTITY_FILTER]); + contentDelimitation = true; + } } MessageBytes valueMB = headers.getValue("host");
test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java+28 −9 modified@@ -98,9 +98,20 @@ public void testKeepAlive() throws Exception { ajpClient.disconnect(); } + @Test + public void testPost() throws Exception { + doTestPost(false, HttpServletResponse.SC_OK); + } + @Test - public void testSimplePost() throws Exception { + public void testPostMultipleContentLength() throws Exception { + // Multiple content lengths + doTestPost(true, HttpServletResponse.SC_BAD_REQUEST); + } + + + public void doTestPost(boolean multipleCL, int expectedStatus) throws Exception { Tomcat tomcat = getTomcatInstance(); @@ -119,6 +130,9 @@ public void testSimplePost() throws Exception { TesterAjpMessage forwardMessage = ajpClient.createForwardMessage("/echo-params.jsp", 4); forwardMessage.addHeader(0xA008, "9"); + if (multipleCL) { + forwardMessage.addHeader(0xA008, "99"); + } forwardMessage.addHeader(0xA007, "application/x-www-form-urlencoded"); forwardMessage.end(); @@ -128,15 +142,20 @@ public void testSimplePost() throws Exception { TesterAjpMessage responseHeaders = ajpClient.sendMessage(forwardMessage, bodyMessage); - // Expect 3 messages: headers, body, end - validateResponseHeaders(responseHeaders, 200); - // Skip the body - TesterAjpMessage responseBody = ajpClient.readMessage(); - validateResponseBody(responseBody, "test - data"); - validateResponseEnd(ajpClient.readMessage(), true); + validateResponseHeaders(responseHeaders, expectedStatus); + if (expectedStatus == HttpServletResponse.SC_OK) { + // Expect 3 messages: headers, body, end for a valid request + TesterAjpMessage responseBody = ajpClient.readMessage(); + validateResponseBody(responseBody, "test - data"); + validateResponseEnd(ajpClient.readMessage(), true); + + // Double check the connection is still open + validateCpong(ajpClient.cping()); + } else { + // Expect 2 messages: headers, end for an invalid request + validateResponseEnd(ajpClient.readMessage(), false); + } - // Double check the connection is still open - validateCpong(ajpClient.cping()); ajpClient.disconnect(); }
test/org/apache/coyote/http11/TestAbstractHttp11Processor.java+48 −0 modified@@ -100,6 +100,54 @@ public void testWithTEBuffered() throws Exception { } + @Test + public void testWithTEChunked() throws Exception { + doTestWithTEChunked(false); + } + + + @Test + public void testWithTEChunkedWithCL() throws Exception { + // Should be ignored + doTestWithTEChunked(true); + } + + + private void doTestWithTEChunked(boolean withCL) + throws Exception { + + Tomcat tomcat = getTomcatInstance(); + + // Use the normal Tomcat ROOT context + File root = new File("test/webapp-3.0"); + tomcat.addWebapp("", root.getAbsolutePath()); + + tomcat.start(); + + String request = + "POST /echo-params.jsp HTTP/1.1" + SimpleHttpClient.CRLF + + "Host: any" + SimpleHttpClient.CRLF + + (withCL ? "Content-length: 1" + SimpleHttpClient.CRLF : "") + + "Transfer-encoding: chunked" + SimpleHttpClient.CRLF + + "Content-Type: application/x-www-form-urlencoded" + + SimpleHttpClient.CRLF + + "Connection: close" + SimpleHttpClient.CRLF + + SimpleHttpClient.CRLF + + "9" + SimpleHttpClient.CRLF + + "test=data" + SimpleHttpClient.CRLF + + "0" + SimpleHttpClient.CRLF + + SimpleHttpClient.CRLF; + + Client client = new Client(tomcat.getConnector().getLocalPort()); + client.setRequest(new String[] {request}); + + client.connect(); + client.processRequest(); + assertTrue(client.isResponse200()); + assertTrue(client.getResponseBody().contains("test - data")); + } + + @Test public void testWithTEIdentity() throws Exception { Tomcat tomcat = getTomcatInstance();
bcce3e4997a4Better adherence to RFC2616 for content-length headers
4 files changed · +67 −15
java/org/apache/coyote/ajp/AbstractAjpProcessor.java+10 −2 modified@@ -29,6 +29,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import javax.servlet.RequestDispatcher; +import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpUpgradeHandler; import org.apache.coyote.AbstractProcessor; @@ -1110,6 +1111,7 @@ protected void prepareRequest() { // Set this every time in case limit has been changed via JMX headers.setLimit(endpoint.getMaxHeaderCount()); + boolean contentLengthSet = false; int hCount = requestHeaderMessage.getInt(); for(int i = 0 ; i < hCount ; i++) { String hName = null; @@ -1144,9 +1146,15 @@ protected void prepareRequest() { if (hId == Constants.SC_REQ_CONTENT_LENGTH || (hId == -1 && tmpMB.equalsIgnoreCase("Content-Length"))) { - // just read the content-length header, so set it long cl = vMB.getLong(); - request.setContentLength(cl); + if (contentLengthSet) { + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + error = true; + } else { + contentLengthSet = true; + // Set the content-length header for the request + request.setContentLength(cl); + } if (cl != 0) { bodyPresent = true; }
java/org/apache/coyote/http11/AbstractHttp11Processor.java+14 −4 modified@@ -1263,10 +1263,20 @@ protected void prepareRequest() { // Parse content-length header long contentLength = request.getContentLengthLong(); - if (contentLength >= 0 && !contentDelimitation) { - getInputBuffer().addActiveFilter - (inputFilters[Constants.IDENTITY_FILTER]); - contentDelimitation = true; + if (contentLength >= 0) { + if (contentDelimitation) { + // contentDelimitation being true at this point indicates that + // chunked encoding is being used but chunked encoding should + // not be used with a content length. RFC 2616, section 4.4, + // bullet 3 states Content-Length must be ignored in this case - + // so remove it. + headers.removeHeader("content-length"); + request.setContentLength(-1); + } else { + getInputBuffer().addActiveFilter + (inputFilters[Constants.IDENTITY_FILTER]); + contentDelimitation = true; + } } MessageBytes valueMB = headers.getValue("host");
test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java+28 −9 modified@@ -98,9 +98,20 @@ public void testKeepAlive() throws Exception { ajpClient.disconnect(); } + @Test + public void testPost() throws Exception { + doTestPost(false, HttpServletResponse.SC_OK); + } + @Test - public void testSimplePost() throws Exception { + public void testPostMultipleContentLength() throws Exception { + // Multiple content lengths + doTestPost(true, HttpServletResponse.SC_BAD_REQUEST); + } + + + public void doTestPost(boolean multipleCL, int expectedStatus) throws Exception { Tomcat tomcat = getTomcatInstance(); @@ -119,6 +130,9 @@ public void testSimplePost() throws Exception { TesterAjpMessage forwardMessage = ajpClient.createForwardMessage("/echo-params.jsp", 4); forwardMessage.addHeader(0xA008, "9"); + if (multipleCL) { + forwardMessage.addHeader(0xA008, "99"); + } forwardMessage.addHeader(0xA007, "application/x-www-form-urlencoded"); forwardMessage.end(); @@ -128,15 +142,20 @@ public void testSimplePost() throws Exception { TesterAjpMessage responseHeaders = ajpClient.sendMessage(forwardMessage, bodyMessage); - // Expect 3 messages: headers, body, end - validateResponseHeaders(responseHeaders, 200); - // Skip the body - TesterAjpMessage responseBody = ajpClient.readMessage(); - validateResponseBody(responseBody, "test - data"); - validateResponseEnd(ajpClient.readMessage(), true); + validateResponseHeaders(responseHeaders, expectedStatus); + if (expectedStatus == HttpServletResponse.SC_OK) { + // Expect 3 messages: headers, body, end for a valid request + TesterAjpMessage responseBody = ajpClient.readMessage(); + validateResponseBody(responseBody, "test - data"); + validateResponseEnd(ajpClient.readMessage(), true); + + // Double check the connection is still open + validateCpong(ajpClient.cping()); + } else { + // Expect 2 messages: headers, end for an invalid request + validateResponseEnd(ajpClient.readMessage(), false); + } - // Double check the connection is still open - validateCpong(ajpClient.cping()); ajpClient.disconnect(); }
test/org/apache/coyote/http11/TestAbstractHttp11Processor.java+15 −0 modified@@ -103,6 +103,20 @@ public void testWithTEBuffered() throws Exception { @Test public void testWithTEChunked() throws Exception { + doTestWithTEChunked(false); + } + + + @Test + public void testWithTEChunkedWithCL() throws Exception { + // Should be ignored + doTestWithTEChunked(true); + } + + + private void doTestWithTEChunked(boolean withCL) + throws Exception { + Tomcat tomcat = getTomcatInstance(); // Use the normal Tomcat ROOT context @@ -114,6 +128,7 @@ public void testWithTEChunked() throws Exception { String request = "POST /echo-params.jsp HTTP/1.1" + SimpleHttpClient.CRLF + "Host: any" + SimpleHttpClient.CRLF + + (withCL ? "Content-length: 1" + SimpleHttpClient.CRLF : "") + "Transfer-encoding: chunked" + SimpleHttpClient.CRLF + "Content-Type: application/x-www-form-urlencoded" + SimpleHttpClient.CRLF +
ff00954b78e6Better adherence to RFC2616 for content-length headers
4 files changed · +67 −15
java/org/apache/coyote/ajp/AbstractAjpProcessor.java+10 −2 modified@@ -29,6 +29,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import javax.servlet.RequestDispatcher; +import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpUpgradeHandler; import org.apache.coyote.AbstractProcessor; @@ -1110,6 +1111,7 @@ protected void prepareRequest() { // Set this every time in case limit has been changed via JMX headers.setLimit(endpoint.getMaxHeaderCount()); + boolean contentLengthSet = false; int hCount = requestHeaderMessage.getInt(); for(int i = 0 ; i < hCount ; i++) { String hName = null; @@ -1144,9 +1146,15 @@ protected void prepareRequest() { if (hId == Constants.SC_REQ_CONTENT_LENGTH || (hId == -1 && tmpMB.equalsIgnoreCase("Content-Length"))) { - // just read the content-length header, so set it long cl = vMB.getLong(); - request.setContentLength(cl); + if (contentLengthSet) { + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + error = true; + } else { + contentLengthSet = true; + // Set the content-length header for the request + request.setContentLength(cl); + } if (cl != 0) { bodyPresent = true; }
java/org/apache/coyote/http11/AbstractHttp11Processor.java+14 −4 modified@@ -1263,10 +1263,20 @@ protected void prepareRequest() { // Parse content-length header long contentLength = request.getContentLengthLong(); - if (contentLength >= 0 && !contentDelimitation) { - getInputBuffer().addActiveFilter - (inputFilters[Constants.IDENTITY_FILTER]); - contentDelimitation = true; + if (contentLength >= 0) { + if (contentDelimitation) { + // contentDelimitation being true at this point indicates that + // chunked encoding is being used but chunked encoding should + // not be used with a content length. RFC 2616, section 4.4, + // bullet 3 states Content-Length must be ignored in this case - + // so remove it. + headers.removeHeader("content-length"); + request.setContentLength(-1); + } else { + getInputBuffer().addActiveFilter + (inputFilters[Constants.IDENTITY_FILTER]); + contentDelimitation = true; + } } MessageBytes valueMB = headers.getValue("host");
test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java+28 −9 modified@@ -98,9 +98,20 @@ public void testKeepAlive() throws Exception { ajpClient.disconnect(); } + @Test + public void testPost() throws Exception { + doTestPost(false, HttpServletResponse.SC_OK); + } + @Test - public void testSimplePost() throws Exception { + public void testPostMultipleContentLength() throws Exception { + // Multiple content lengths + doTestPost(true, HttpServletResponse.SC_BAD_REQUEST); + } + + + public void doTestPost(boolean multipleCL, int expectedStatus) throws Exception { Tomcat tomcat = getTomcatInstance(); @@ -119,6 +130,9 @@ public void testSimplePost() throws Exception { TesterAjpMessage forwardMessage = ajpClient.createForwardMessage("/echo-params.jsp", 4); forwardMessage.addHeader(0xA008, "9"); + if (multipleCL) { + forwardMessage.addHeader(0xA008, "99"); + } forwardMessage.addHeader(0xA007, "application/x-www-form-urlencoded"); forwardMessage.end(); @@ -128,15 +142,20 @@ public void testSimplePost() throws Exception { TesterAjpMessage responseHeaders = ajpClient.sendMessage(forwardMessage, bodyMessage); - // Expect 3 messages: headers, body, end - validateResponseHeaders(responseHeaders, 200); - // Skip the body - TesterAjpMessage responseBody = ajpClient.readMessage(); - validateResponseBody(responseBody, "test - data"); - validateResponseEnd(ajpClient.readMessage(), true); + validateResponseHeaders(responseHeaders, expectedStatus); + if (expectedStatus == HttpServletResponse.SC_OK) { + // Expect 3 messages: headers, body, end for a valid request + TesterAjpMessage responseBody = ajpClient.readMessage(); + validateResponseBody(responseBody, "test - data"); + validateResponseEnd(ajpClient.readMessage(), true); + + // Double check the connection is still open + validateCpong(ajpClient.cping()); + } else { + // Expect 2 messages: headers, end for an invalid request + validateResponseEnd(ajpClient.readMessage(), false); + } - // Double check the connection is still open - validateCpong(ajpClient.cping()); ajpClient.disconnect(); }
test/org/apache/coyote/http11/TestAbstractHttp11Processor.java+15 −0 modified@@ -103,6 +103,20 @@ public void testWithTEBuffered() throws Exception { @Test public void testWithTEChunked() throws Exception { + doTestWithTEChunked(false); + } + + + @Test + public void testWithTEChunkedWithCL() throws Exception { + // Should be ignored + doTestWithTEChunked(true); + } + + + private void doTestWithTEChunked(boolean withCL) + throws Exception { + Tomcat tomcat = getTomcatInstance(); // Use the normal Tomcat ROOT context @@ -114,6 +128,7 @@ public void testWithTEChunked() throws Exception { String request = "POST /echo-params.jsp HTTP/1.1" + SimpleHttpClient.CRLF + "Host: any" + SimpleHttpClient.CRLF + + (withCL ? "Content-length: 1" + SimpleHttpClient.CRLF : "") + "Transfer-encoding: chunked" + SimpleHttpClient.CRLF + "Content-Type: application/x-www-form-urlencoded" + SimpleHttpClient.CRLF +
d0b3e252eb16Content length is managed internally as a long. Fix a few places that were unnecessarily restricting it to an int.
3 files changed · +7 −4
java/org/apache/coyote/ajp/AbstractAjpProcessor.java+1 −3 modified@@ -707,9 +707,7 @@ protected void prepareRequest() { if (hId == Constants.SC_REQ_CONTENT_LENGTH || (hId == -1 && tmpMB.equalsIgnoreCase("Content-Length"))) { // just read the content-length header, so set it - long cl = vMB.getLong(); - if(cl < Integer.MAX_VALUE) - request.setContentLength( (int)cl ); + request.setContentLength(vMB.getLong()); } else if (hId == Constants.SC_REQ_CONTENT_TYPE || (hId == -1 && tmpMB.equalsIgnoreCase("Content-Type"))) { // just read the content-type header, so set it
java/org/apache/coyote/Request.java+1 −1 modified@@ -272,7 +272,7 @@ public void setCharacterEncoding(String enc) { } - public void setContentLength(int len) { + public void setContentLength(long len) { this.contentLength = len; }
webapps/docs/changelog.xml+5 −0 modified@@ -176,6 +176,11 @@ APR/native and HTTP APR/native connectors no longer support multiple poller threads. Both connectors now use a single poller thread. (markt) </update> + <fix> + Internally, content length is managed as a <code>long</code>. Fix a few + places in the AJP connector where this was restricted to an + <code>int</code>. (markt) + </fix> </changelog> </subsection> <subsection name="Jasper">
7c040003f138Content length is managed internally as a long. Fix a few places that were unnecessarily restricting it to an int.
2 files changed · +2 −4
java/org/apache/coyote/ajp/AbstractAjpProcessor.java+1 −3 modified@@ -688,9 +688,7 @@ protected void prepareRequest() { if (hId == Constants.SC_REQ_CONTENT_LENGTH || (hId == -1 && tmpMB.equalsIgnoreCase("Content-Length"))) { // just read the content-length header, so set it - long cl = vMB.getLong(); - if(cl < Integer.MAX_VALUE) - request.setContentLength( (int)cl ); + request.setContentLength(vMB.getLong()); } else if (hId == Constants.SC_REQ_CONTENT_TYPE || (hId == -1 && tmpMB.equalsIgnoreCase("Content-Type"))) { // just read the content-type header, so set it
java/org/apache/coyote/Request.java+1 −1 modified@@ -296,7 +296,7 @@ public void setCharacterEncoding(String enc) { } - public void setContentLength(int len) { + public void setContentLength(long len) { this.contentLength = len; }
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
72- tomcat.apache.org/security-6.htmlnvdVendor AdvisoryWEB
- tomcat.apache.org/security-7.htmlnvdVendor AdvisoryWEB
- tomcat.apache.org/security-8.htmlnvdVendor AdvisoryWEB
- github.com/advisories/GHSA-j448-j653-r3vjghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2013-4286ghsaADVISORY
- advisories.mageia.org/MGASA-2014-0148.htmlnvdWEB
- marc.infonvdWEB
- marc.infonvdWEB
- rhn.redhat.com/errata/RHSA-2014-0343.htmlnvdWEB
- rhn.redhat.com/errata/RHSA-2014-0344.htmlnvdWEB
- rhn.redhat.com/errata/RHSA-2014-0345.htmlnvdWEB
- svn.apache.org/viewvcnvdWEB
- svn.apache.org/viewvcnvdWEB
- svn.apache.org/viewvcnvdWEB
- www-01.ibm.com/support/docview.wssnvdWEB
- www.debian.org/security/2016/dsa-3530nvdWEB
- www.mandriva.com/security/advisoriesnvdWEB
- www.oracle.com/technetwork/security-advisory/cpuoct2016-2881722.htmlnvdWEB
- www.oracle.com/technetwork/topics/security/cpuapr2015-2365600.htmlnvdWEB
- www.oracle.com/technetwork/topics/security/cpujan2015-1972971.htmlnvdWEB
- www.oracle.com/technetwork/topics/security/cpujul2014-1972956.htmlnvdWEB
- www.oracle.com/technetwork/topics/security/cpuoct2014-1972960.htmlnvdWEB
- www.ubuntu.com/usn/USN-2130-1nvdWEB
- www.vmware.com/security/advisories/VMSA-2014-0012.htmlnvdWEB
- bugzilla.redhat.com/show_bug.cginvdWEB
- github.com/apache/tomcat/commit/41b90b6ebc3e7f898a5a87d197ddf63790d33315ghsaWEB
- github.com/apache/tomcat/commit/7c040003f1387795356605566be7870cf70e05dcghsaWEB
- github.com/apache/tomcat/commit/bcce3e4997a4ed06fe03e2517443f3ad8ade2dfaghsaWEB
- github.com/apache/tomcat/commit/d0b3e252eb168fafbfb4c3efc16d4192fc8fad6cghsaWEB
- github.com/apache/tomcat80/commit/ff00954b78e6484e40f323c0cef2e6d95c2882b9ghsaWEB
- h20564.www2.hpe.com/portal/site/hpsc/public/kb/docDisplaynvdWEB
- lists.apache.org/thread.html/37220405a377c0182d2afdbc36461c4783b2930fbeae3a17f1333113@%3Cdev.tomcat.apache.org%3EghsaWEB
- lists.apache.org/thread.html/39ae1f0bd5867c15755a6f959b271ade1aea04ccdc3b2e639dcd903b@%3Cdev.tomcat.apache.org%3EghsaWEB
- lists.apache.org/thread.html/b84ad1258a89de5c9c853c7f2d3ad77e5b8b2930be9e132d5cef6b95@%3Cdev.tomcat.apache.org%3EghsaWEB
- lists.apache.org/thread.html/b8a1bf18155b552dcf9a928ba808cbadad84c236d85eab3033662cfb@%3Cdev.tomcat.apache.org%3EghsaWEB
- lists.apache.org/thread.html/r03c597a64de790ba42c167efacfa23300c3d6c9fe589ab87fe02859c@%3Cdev.tomcat.apache.org%3EghsaWEB
- lists.apache.org/thread.html/r587e50b86c1a96ee301f751d50294072d142fd6dc08a8987ae9f3a9b@%3Cdev.tomcat.apache.org%3EghsaWEB
- rhn.redhat.com/errata/RHSA-2014-0686.htmlnvdWEB
- web.archive.org/web/20140724174205/http://secunia.com/advisories/57675ghsaWEB
- web.archive.org/web/20140804172142/http://secunia.com/advisories/59036ghsaWEB
- web.archive.org/web/20141230041748/http://seclists.org/fulldisclosure/2014/Dec/23ghsaWEB
- web.archive.org/web/20160317145515/http://www.securityfocus.com/archive/1/534161/100/0/threadedghsaWEB
- web.archive.org/web/20160729061926/http://www.securityfocus.com/bid/65773ghsaWEB
- web.archive.org/web/20161014054543/http://www-01.ibm.com/support/docview.wssghsaWEB
- web.archive.org/web/20161014054838/http://www-01.ibm.com/support/docview.wssghsaWEB
- web.archive.org/web/20161014054913/http://www-01.ibm.com/support/docview.wssghsaWEB
- web.archive.org/web/20161014054948/http://www-01.ibm.com/support/docview.wssghsaWEB
- web.archive.org/web/20161024215453/http://secunia.com/advisories/59873ghsaWEB
- web.archive.org/web/20161024215639/http://secunia.com/advisories/59722ghsaWEB
- web.archive.org/web/20161024215804/http://secunia.com/advisories/59675ghsaWEB
- web.archive.org/web/20161024220018/http://secunia.com/advisories/59724ghsaWEB
- web.archive.org/web/20161024220034/http://secunia.com/advisories/59733ghsaWEB
- seclists.org/fulldisclosure/2014/Dec/23nvd
- secunia.com/advisories/57675nvd
- secunia.com/advisories/59036nvd
- secunia.com/advisories/59675nvd
- secunia.com/advisories/59722nvd
- secunia.com/advisories/59724nvd
- secunia.com/advisories/59733nvd
- secunia.com/advisories/59873nvd
- www-01.ibm.com/support/docview.wssnvd
- www-01.ibm.com/support/docview.wssnvd
- www-01.ibm.com/support/docview.wssnvd
- www-01.ibm.com/support/docview.wssnvd
- www.securityfocus.com/archive/1/534161/100/0/threadednvd
- www.securityfocus.com/bid/65773nvd
- lists.apache.org/thread.html/37220405a377c0182d2afdbc36461c4783b2930fbeae3a17f1333113%40%3Cdev.tomcat.apache.org%3Envd
- lists.apache.org/thread.html/39ae1f0bd5867c15755a6f959b271ade1aea04ccdc3b2e639dcd903b%40%3Cdev.tomcat.apache.org%3Envd
- lists.apache.org/thread.html/b84ad1258a89de5c9c853c7f2d3ad77e5b8b2930be9e132d5cef6b95%40%3Cdev.tomcat.apache.org%3Envd
- lists.apache.org/thread.html/b8a1bf18155b552dcf9a928ba808cbadad84c236d85eab3033662cfb%40%3Cdev.tomcat.apache.org%3Envd
- lists.apache.org/thread.html/r03c597a64de790ba42c167efacfa23300c3d6c9fe589ab87fe02859c%40%3Cdev.tomcat.apache.org%3Envd
- lists.apache.org/thread.html/r587e50b86c1a96ee301f751d50294072d142fd6dc08a8987ae9f3a9b%40%3Cdev.tomcat.apache.org%3Envd
News mentions
0No linked articles in our index yet.