VYPR
Moderate severityNVD Advisory· Published Feb 26, 2014· Updated Apr 29, 2026

CVE-2013-4286

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.

PackageAffected versionsPatched versions
org.apache.tomcat:tomcatMaven
< 6.0.396.0.39
org.apache.tomcat:tomcatMaven
>= 7.0.0, < 7.0.477.0.47
org.apache.tomcat:tomcatMaven
>= 8.0.0-RC1, < 8.0.0-RC38.0.0-RC3

Affected products

184
  • Apache/Tomcat183 versions
    cpe: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:*:*:*:*:*:*
  • ghsa-coords
    Range: < 6.0.39

Patches

5
41b90b6ebc3e

Better adherence to RFC2616 for content-length headers

https://github.com/apache/tomcatMark Emlyn David ThomasSep 11, 2013via ghsa
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();
    
bcce3e4997a4

Better adherence to RFC2616 for content-length headers

https://github.com/apache/tomcatMark Emlyn David ThomasSep 11, 2013via ghsa
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 +
    
ff00954b78e6

Better adherence to RFC2616 for content-length headers

https://github.com/apache/tomcat80Mark ThomasSep 11, 2013via ghsa
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 +
    
d0b3e252eb16

Content length is managed internally as a long. Fix a few places that were unnecessarily restricting it to an int.

https://github.com/apache/tomcatMark Emlyn David ThomasAug 28, 2013via ghsa
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">
    
7c040003f138

Content length is managed internally as a long. Fix a few places that were unnecessarily restricting it to an int.

https://github.com/apache/tomcatMark Emlyn David ThomasAug 27, 2013via ghsa
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

News mentions

0

No linked articles in our index yet.