VYPR
Moderate severityNVD Advisory· Published Jul 12, 2021· Updated Aug 3, 2024

Incorrect Transfer-Encoding handling with HTTP/1.0

CVE-2021-33037

Description

Apache Tomcat 10.0.0-M1 to 10.0.6, 9.0.0.M1 to 9.0.46 and 8.5.0 to 8.5.66 did not correctly parse the HTTP transfer-encoding request header in some circumstances leading to the possibility to request smuggling when used with a reverse proxy. Specifically: - Tomcat incorrectly ignored the transfer encoding header if the client declared it would only accept an HTTP/1.0 response; - Tomcat honoured the identify encoding; and - Tomcat did not ensure that, if present, the chunked encoding was the final encoding.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Apache Tomcat improperly parses HTTP transfer-encoding headers allowing request smuggling when behind a reverse proxy.

Vulnerability

Apache Tomcat versions 10.0.0-M1 to 10.0.6, 9.0.0.M1 to 9.0.46, and 8.5.0 to 8.5.66 incorrectly parse the HTTP Transfer-Encoding request header. The parsing fails in three ways: (1) ignoring the header if the client declares HTTP/1.0 response only; (2) honouring the identity encoding; (3) not ensuring chunked is the final encoding. This occurs in Tomcat's HTTP connector when behind a reverse proxy [1][2][3][4].

Exploitation

An attacker with network access to send HTTP requests to the reverse proxy can craft a request with a malformed Transfer-Encoding header that exploits Tomcat's parsing flaws. The reverse proxy forwards the request to Tomcat, which misinterprets the body boundaries, leading to request smuggling. No authentication is required, and the attacker must be able to control request headers [4].

Impact

Successful exploitation allows the attacker to smuggle a request past the reverse proxy, enabling request hijacking, cache poisoning, or bypass of security controls. The impact depends on the proxy configuration but can lead to disclosure of internal data or unauthorized actions [4].

Mitigation

Upgrade to Apache Tomcat 8.5.67, 9.0.47, or 10.0.7 or later. No workarounds are disclosed in the available references. Users on unsupported branches (8.5.x EOL, 10.0.x EOL) must upgrade to supported releases [1][2][3].

AI Insight generated on May 21, 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
>= 10.0.0-M1, < 10.0.710.0.7
org.apache.tomcat:tomcatMaven
>= 9.0.0-M1, < 9.0.489.0.48
org.apache.tomcat:tomcatMaven
>= 8.5.0, < 8.5.688.5.68

Affected products

33

Patches

9
19d11556d0db

Ensure chunked, if present, is the last encoding in the list

https://github.com/apache/tomcatMark ThomasMay 10, 2021via ghsa
3 files changed · +36 10
  • java/org/apache/coyote/http11/Http11Processor.java+12 1 modified
    @@ -209,9 +209,20 @@ private static boolean statusDropsConnection(int status) {
          * supported, a 501 response will be returned to the client.
          */
         private void addInputFilter(InputFilter[] inputFilters, String encodingName) {
    +        if (contentDelimitation) {
    +            // Chunked has already been specified and it must be the final
    +            // encoding.
    +            // 400 - Bad request
    +            response.setStatus(400);
    +            setErrorState(ErrorState.CLOSE_CLEAN, null);
    +            if (log.isDebugEnabled()) {
    +                log.debug(sm.getString("http11processor.request.prepare") +
    +                          " Tranfer encoding lists chunked before [" + encodingName + "]");
    +            }
    +            return;
    +        }
     
             // Parsing trims and converts to lower case.
    -
             if (encodingName.equals("chunked")) {
                 inputBuffer.addActiveFilter(inputFilters[Constants.CHUNKED_FILTER]);
                 contentDelimitation = true;
    
  • test/org/apache/coyote/http11/TestHttp11Processor.java+19 9 modified
    @@ -1838,47 +1838,53 @@ public void onError(Throwable throwable) {
     
         @Test
         public void testTEHeaderUnknown01() throws Exception {
    -        doTestTEHeaderUnknown("identity");
    +        doTestTEHeaderInvalid("identity", false);
         }
     
     
         @Test
         public void testTEHeaderUnknown02() throws Exception {
    -        doTestTEHeaderUnknown("identity, chunked");
    +        doTestTEHeaderInvalid("identity, chunked", false);
         }
     
     
         @Test
         public void testTEHeaderUnknown03() throws Exception {
    -        doTestTEHeaderUnknown("unknown, chunked");
    +        doTestTEHeaderInvalid("unknown, chunked", false);
         }
     
     
         @Test
         public void testTEHeaderUnknown04() throws Exception {
    -        doTestTEHeaderUnknown("void");
    +        doTestTEHeaderInvalid("void", false);
         }
     
     
         @Test
         public void testTEHeaderUnknown05() throws Exception {
    -        doTestTEHeaderUnknown("void, chunked");
    +        doTestTEHeaderInvalid("void, chunked", false);
         }
     
     
         @Test
         public void testTEHeaderUnknown06() throws Exception {
    -        doTestTEHeaderUnknown("void, identity");
    +        doTestTEHeaderInvalid("void, identity", false);
         }
     
     
         @Test
         public void testTEHeaderUnknown07() throws Exception {
    -        doTestTEHeaderUnknown("identity, void");
    +        doTestTEHeaderInvalid("identity, void", false);
         }
     
     
    -    private void doTestTEHeaderUnknown(String headerValue) throws Exception {
    +    @Test
    +    public void testTEHeaderChunkedNotLast01() throws Exception {
    +        doTestTEHeaderInvalid("chunked, void", true);
    +    }
    +
    +
    +    private void doTestTEHeaderInvalid(String headerValue, boolean badRequest) throws Exception {
             Tomcat tomcat = getTomcatInstance();
     
             // No file system docBase required
    @@ -1902,7 +1908,11 @@ private void doTestTEHeaderUnknown(String headerValue) throws Exception {
             client.connect();
             client.processRequest(false);
     
    -        Assert.assertTrue(client.isResponse501());
    +        if (badRequest) {
    +            Assert.assertTrue(client.isResponse400());
    +        } else {
    +            Assert.assertTrue(client.isResponse501());
    +        }
         }
     
     
    
  • webapps/docs/changelog.xml+5 0 modified
    @@ -202,6 +202,11 @@
             Process transfer encoding headers from both HTTP 1.0 and HTTP 1.1
             clients. (markt)
           </fix>
    +      <fix>
    +        Ensure that if the transfer encoding header contains the
    +        <code>chunked</code>, that the <code>chunked</code> encoding is the
    +        final encoding listed. (markt)
    +      </fix>
         </changelog>
       </subsection>
       <subsection name="Jasper">
    
8874fa02e9b3

Ensure chunked, if present, is the last encoding in the list

https://github.com/apache/tomcatMark ThomasMay 10, 2021via ghsa
3 files changed · +36 10
  • java/org/apache/coyote/http11/Http11Processor.java+12 1 modified
    @@ -451,9 +451,20 @@ private static boolean statusDropsConnection(int status) {
          * supported, a 501 response will be returned to the client.
          */
         private void addInputFilter(InputFilter[] inputFilters, String encodingName) {
    +        if (contentDelimitation) {
    +            // Chunked has already been specified and it must be the final
    +            // encoding.
    +            // 400 - Bad request
    +            response.setStatus(400);
    +            setErrorState(ErrorState.CLOSE_CLEAN, null);
    +            if (log.isDebugEnabled()) {
    +                log.debug(sm.getString("http11processor.request.prepare") +
    +                          " Tranfer encoding lists chunked before [" + encodingName + "]");
    +            }
    +            return;
    +        }
     
             // Parsing trims and converts to lower case.
    -
             if (encodingName.equals("chunked")) {
                 inputBuffer.addActiveFilter(inputFilters[Constants.CHUNKED_FILTER]);
                 contentDelimitation = true;
    
  • test/org/apache/coyote/http11/TestHttp11Processor.java+19 9 modified
    @@ -1854,47 +1854,53 @@ public void onError(Throwable throwable) {
     
         @Test
         public void testTEHeaderUnknown01() throws Exception {
    -        doTestTEHeaderUnknown("identity");
    +        doTestTEHeaderInvalid("identity", false);
         }
     
     
         @Test
         public void testTEHeaderUnknown02() throws Exception {
    -        doTestTEHeaderUnknown("identity, chunked");
    +        doTestTEHeaderInvalid("identity, chunked", false);
         }
     
     
         @Test
         public void testTEHeaderUnknown03() throws Exception {
    -        doTestTEHeaderUnknown("unknown, chunked");
    +        doTestTEHeaderInvalid("unknown, chunked", false);
         }
     
     
         @Test
         public void testTEHeaderUnknown04() throws Exception {
    -        doTestTEHeaderUnknown("void");
    +        doTestTEHeaderInvalid("void", false);
         }
     
     
         @Test
         public void testTEHeaderUnknown05() throws Exception {
    -        doTestTEHeaderUnknown("void, chunked");
    +        doTestTEHeaderInvalid("void, chunked", false);
         }
     
     
         @Test
         public void testTEHeaderUnknown06() throws Exception {
    -        doTestTEHeaderUnknown("void, identity");
    +        doTestTEHeaderInvalid("void, identity", false);
         }
     
     
         @Test
         public void testTEHeaderUnknown07() throws Exception {
    -        doTestTEHeaderUnknown("identity, void");
    +        doTestTEHeaderInvalid("identity, void", false);
         }
     
     
    -    private void doTestTEHeaderUnknown(String headerValue) throws Exception {
    +    @Test
    +    public void testTEHeaderChunkedNotLast01() throws Exception {
    +        doTestTEHeaderInvalid("chunked, void", true);
    +    }
    +
    +
    +    private void doTestTEHeaderInvalid(String headerValue, boolean badRequest) throws Exception {
             Tomcat tomcat = getTomcatInstance();
     
             // No file system docBase required
    @@ -1918,7 +1924,11 @@ private void doTestTEHeaderUnknown(String headerValue) throws Exception {
             client.connect();
             client.processRequest(false);
     
    -        Assert.assertTrue(client.isResponse501());
    +        if (badRequest) {
    +            Assert.assertTrue(client.isResponse400());
    +        } else {
    +            Assert.assertTrue(client.isResponse501());
    +        }
         }
     
     
    
  • webapps/docs/changelog.xml+5 0 modified
    @@ -216,6 +216,11 @@
             Process transfer encoding headers from both HTTP 1.0 and HTTP 1.1
             clients. (markt)
           </fix>
    +      <fix>
    +        Ensure that if the transfer encoding header contains the
    +        <code>chunked</code>, that the <code>chunked</code> encoding is the
    +        final encoding listed. (markt)
    +      </fix>
         </changelog>
       </subsection>
       <subsection name="Jasper">
    
a2c3dc4c9616

Ensure chunked, if present, is the last encoding in the list

https://github.com/apache/tomcatMark ThomasMay 10, 2021via ghsa
3 files changed · +36 10
  • java/org/apache/coyote/http11/Http11Processor.java+12 1 modified
    @@ -209,9 +209,20 @@ private static boolean statusDropsConnection(int status) {
          * supported, a 501 response will be returned to the client.
          */
         private void addInputFilter(InputFilter[] inputFilters, String encodingName) {
    +        if (contentDelimitation) {
    +            // Chunked has already been specified and it must be the final
    +            // encoding.
    +            // 400 - Bad request
    +            response.setStatus(400);
    +            setErrorState(ErrorState.CLOSE_CLEAN, null);
    +            if (log.isDebugEnabled()) {
    +                log.debug(sm.getString("http11processor.request.prepare") +
    +                          " Tranfer encoding lists chunked before [" + encodingName + "]");
    +            }
    +            return;
    +        }
     
             // Parsing trims and converts to lower case.
    -
             if (encodingName.equals("chunked")) {
                 inputBuffer.addActiveFilter(inputFilters[Constants.CHUNKED_FILTER]);
                 contentDelimitation = true;
    
  • test/org/apache/coyote/http11/TestHttp11Processor.java+19 9 modified
    @@ -1838,47 +1838,53 @@ public void onError(Throwable throwable) {
     
         @Test
         public void testTEHeaderUnknown01() throws Exception {
    -        doTestTEHeaderUnknown("identity");
    +        doTestTEHeaderInvalid("identity", false);
         }
     
     
         @Test
         public void testTEHeaderUnknown02() throws Exception {
    -        doTestTEHeaderUnknown("identity, chunked");
    +        doTestTEHeaderInvalid("identity, chunked", false);
         }
     
     
         @Test
         public void testTEHeaderUnknown03() throws Exception {
    -        doTestTEHeaderUnknown("unknown, chunked");
    +        doTestTEHeaderInvalid("unknown, chunked", false);
         }
     
     
         @Test
         public void testTEHeaderUnknown04() throws Exception {
    -        doTestTEHeaderUnknown("void");
    +        doTestTEHeaderInvalid("void", false);
         }
     
     
         @Test
         public void testTEHeaderUnknown05() throws Exception {
    -        doTestTEHeaderUnknown("void, chunked");
    +        doTestTEHeaderInvalid("void, chunked", false);
         }
     
     
         @Test
         public void testTEHeaderUnknown06() throws Exception {
    -        doTestTEHeaderUnknown("void, identity");
    +        doTestTEHeaderInvalid("void, identity", false);
         }
     
     
         @Test
         public void testTEHeaderUnknown07() throws Exception {
    -        doTestTEHeaderUnknown("identity, void");
    +        doTestTEHeaderInvalid("identity, void", false);
         }
     
     
    -    private void doTestTEHeaderUnknown(String headerValue) throws Exception {
    +    @Test
    +    public void testTEHeaderChunkedNotLast01() throws Exception {
    +        doTestTEHeaderInvalid("chunked, void", true);
    +    }
    +
    +
    +    private void doTestTEHeaderInvalid(String headerValue, boolean badRequest) throws Exception {
             Tomcat tomcat = getTomcatInstance();
     
             // No file system docBase required
    @@ -1902,7 +1908,11 @@ private void doTestTEHeaderUnknown(String headerValue) throws Exception {
             client.connect();
             client.processRequest(false);
     
    -        Assert.assertTrue(client.isResponse501());
    +        if (badRequest) {
    +            Assert.assertTrue(client.isResponse400());
    +        } else {
    +            Assert.assertTrue(client.isResponse501());
    +        }
         }
     
     
    
  • webapps/docs/changelog.xml+5 0 modified
    @@ -228,6 +228,11 @@
             Process transfer encoding headers from both HTTP 1.0 and HTTP 1.1
             clients. (markt)
           </fix>
    +      <fix>
    +        Ensure that if the transfer encoding header contains the
    +        <code>chunked</code>, that the <code>chunked</code> encoding is the
    +        final encoding listed. (markt)
    +      </fix>
         </changelog>
       </subsection>
       <subsection name="Jasper">
    
05f9e8b00f5d

Process T-E header from both HTTP 1.0 and HTTP 1.1. clients

https://github.com/apache/tomcatMark ThomasMay 10, 2021via ghsa
3 files changed · +35 1
  • java/org/apache/coyote/http11/Http11Processor.java+3 1 modified
    @@ -750,7 +750,9 @@ private void prepareRequest() throws IOException {
             InputFilter[] inputFilters = inputBuffer.getFilters();
     
             // Parse transfer-encoding header
    -        if (http11) {
    +        // HTTP specs say an HTTP 1.1 server should accept any recognised
    +        // HTTP 1.x header from a 1.x client unless the specs says otherwise.
    +        if (!http09) {
                 MessageBytes transferEncodingValueMB = headers.getValue("transfer-encoding");
                 if (transferEncodingValueMB != null) {
                     List<String> encodingNames = new ArrayList<>();
    
  • test/org/apache/coyote/http11/TestHttp11Processor.java+28 0 modified
    @@ -1904,4 +1904,32 @@ private void doTestTEHeaderUnknown(String headerValue) throws Exception {
     
             Assert.assertTrue(client.isResponse501());
         }
    +
    +
    +    @Test
    +    public void testWithTEChunkedHttp10() throws Exception {
    +
    +        getTomcatInstanceTestWebapp(false, true);
    +
    +        String request =
    +            "POST /test/echo-params.jsp HTTP/1.0" + SimpleHttpClient.CRLF +
    +            "Host: any" + 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(getPort());
    +        client.setRequest(new String[] {request});
    +
    +        client.connect();
    +        client.processRequest();
    +        Assert.assertTrue(client.isResponse200());
    +        Assert.assertTrue(client.getResponseBody().contains("test - data"));
    +    }
     }
    
  • webapps/docs/changelog.xml+4 0 modified
    @@ -224,6 +224,10 @@
             in 2001. Requests using this transfer encoding will now receive a 501
             response. (markt)
           </fix>
    +      <fix>
    +        Process transfer encoding headers from both HTTP 1.0 and HTTP 1.1
    +        clients. (markt)
    +      </fix>
         </changelog>
       </subsection>
       <subsection name="Jasper">
    
da0e7cb093cf

Process T-E header from both HTTP 1.0 and HTTP 1.1. clients

https://github.com/apache/tomcatMark ThomasMay 10, 2021via ghsa
3 files changed · +35 1
  • java/org/apache/coyote/http11/Http11Processor.java+3 1 modified
    @@ -992,7 +992,9 @@ private void prepareRequest() throws IOException {
             InputFilter[] inputFilters = inputBuffer.getFilters();
     
             // Parse transfer-encoding header
    -        if (http11) {
    +        // HTTP specs say an HTTP 1.1 server should accept any recognised
    +        // HTTP 1.x header from a 1.x client unless the specs says otherwise.
    +        if (!http09) {
                 MessageBytes transferEncodingValueMB = headers.getValue("transfer-encoding");
                 if (transferEncodingValueMB != null) {
                     List<String> encodingNames = new ArrayList<>();
    
  • test/org/apache/coyote/http11/TestHttp11Processor.java+28 0 modified
    @@ -1920,4 +1920,32 @@ private void doTestTEHeaderUnknown(String headerValue) throws Exception {
     
             Assert.assertTrue(client.isResponse501());
         }
    +
    +
    +    @Test
    +    public void testWithTEChunkedHttp10() throws Exception {
    +
    +        getTomcatInstanceTestWebapp(false, true);
    +
    +        String request =
    +            "POST /test/echo-params.jsp HTTP/1.0" + SimpleHttpClient.CRLF +
    +            "Host: any" + 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(getPort());
    +        client.setRequest(new String[] {request});
    +
    +        client.connect();
    +        client.processRequest();
    +        Assert.assertTrue(client.isResponse200());
    +        Assert.assertTrue(client.getResponseBody().contains("test - data"));
    +    }
     }
    
  • webapps/docs/changelog.xml+4 0 modified
    @@ -212,6 +212,10 @@
             in 2001. Requests using this transfer encoding will now receive a 501
             response. (markt)
           </fix>
    +      <fix>
    +        Process transfer encoding headers from both HTTP 1.0 and HTTP 1.1
    +        clients. (markt)
    +      </fix>
         </changelog>
       </subsection>
       <subsection name="Jasper">
    
506134f957a4

Process T-E header from both HTTP 1.0 and HTTP 1.1. clients

https://github.com/apache/tomcatMark ThomasMay 10, 2021via ghsa
3 files changed · +35 1
  • java/org/apache/coyote/http11/Http11Processor.java+3 1 modified
    @@ -750,7 +750,9 @@ private void prepareRequest() throws IOException {
             InputFilter[] inputFilters = inputBuffer.getFilters();
     
             // Parse transfer-encoding header
    -        if (http11) {
    +        // HTTP specs say an HTTP 1.1 server should accept any recognised
    +        // HTTP 1.x header from a 1.x client unless the specs says otherwise.
    +        if (!http09) {
                 MessageBytes transferEncodingValueMB = headers.getValue("transfer-encoding");
                 if (transferEncodingValueMB != null) {
                     List<String> encodingNames = new ArrayList<>();
    
  • test/org/apache/coyote/http11/TestHttp11Processor.java+28 0 modified
    @@ -1904,4 +1904,32 @@ private void doTestTEHeaderUnknown(String headerValue) throws Exception {
     
             Assert.assertTrue(client.isResponse501());
         }
    +
    +
    +    @Test
    +    public void testWithTEChunkedHttp10() throws Exception {
    +
    +        getTomcatInstanceTestWebapp(false, true);
    +
    +        String request =
    +            "POST /test/echo-params.jsp HTTP/1.0" + SimpleHttpClient.CRLF +
    +            "Host: any" + 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(getPort());
    +        client.setRequest(new String[] {request});
    +
    +        client.connect();
    +        client.processRequest();
    +        Assert.assertTrue(client.isResponse200());
    +        Assert.assertTrue(client.getResponseBody().contains("test - data"));
    +    }
     }
    
  • webapps/docs/changelog.xml+4 0 modified
    @@ -198,6 +198,10 @@
             in 2001. Requests using this transfer encoding will now receive a 501
             response. (markt)
           </fix>
    +      <fix>
    +        Process transfer encoding headers from both HTTP 1.0 and HTTP 1.1
    +        clients. (markt)
    +      </fix>
         </changelog>
       </subsection>
       <subsection name="Jasper">
    
eee0d024c1b3

Remove support for the identity T-E header value

https://github.com/apache/tomcatMark ThomasMay 10, 2021via ghsa
3 files changed · +78 31
  • java/org/apache/coyote/http11/Http11Processor.java+2 6 modified
    @@ -212,11 +212,8 @@ private void addInputFilter(InputFilter[] inputFilters, String encodingName) {
     
             // Parsing trims and converts to lower case.
     
    -        if (encodingName.equals("identity")) {
    -            // Skip
    -        } else if (encodingName.equals("chunked")) {
    -            inputBuffer.addActiveFilter
    -                (inputFilters[Constants.CHUNKED_FILTER]);
    +        if (encodingName.equals("chunked")) {
    +            inputBuffer.addActiveFilter(inputFilters[Constants.CHUNKED_FILTER]);
                 contentDelimitation = true;
             } else {
                 for (int i = pluggableFilterIndex; i < inputFilters.length; i++) {
    @@ -759,7 +756,6 @@ private void prepareRequest() throws IOException {
                     List<String> encodingNames = new ArrayList<>();
                     if (TokenList.parseTokenList(headers.values("transfer-encoding"), encodingNames)) {
                         for (String encodingName : encodingNames) {
    -                        // "identity" codings are ignored
                             addInputFilter(inputFilters, encodingName);
                         }
                     } else {
    
  • test/org/apache/coyote/http11/TestHttp11Processor.java+70 25 modified
    @@ -253,31 +253,6 @@ private void doTestWithTEChunked(boolean withCL) throws Exception {
         }
     
     
    -    @Test
    -    public void testWithTEIdentity() throws Exception {
    -        getTomcatInstanceTestWebapp(false, true);
    -
    -        String request =
    -            "POST /test/echo-params.jsp HTTP/1.1" + SimpleHttpClient.CRLF +
    -            "Host: any" + SimpleHttpClient.CRLF +
    -            "Transfer-encoding: identity" + SimpleHttpClient.CRLF +
    -            "Content-Length: 9" + SimpleHttpClient.CRLF +
    -            "Content-Type: application/x-www-form-urlencoded" +
    -                    SimpleHttpClient.CRLF +
    -            "Connection: close" + SimpleHttpClient.CRLF +
    -                SimpleHttpClient.CRLF +
    -            "test=data";
    -
    -        Client client = new Client(getPort());
    -        client.setRequest(new String[] {request});
    -
    -        client.connect();
    -        client.processRequest();
    -        Assert.assertTrue(client.isResponse200());
    -        Assert.assertTrue(client.getResponseBody().contains("test - data"));
    -    }
    -
    -
         @Test
         public void testWithTESavedRequest() throws Exception {
             getTomcatInstanceTestWebapp(false, true);
    @@ -1859,4 +1834,74 @@ public void onError(Throwable throwable) {
                 // NO-OP
             }
         }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown01() throws Exception {
    +        doTestTEHeaderUnknown("identity");
    +    }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown02() throws Exception {
    +        doTestTEHeaderUnknown("identity, chunked");
    +    }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown03() throws Exception {
    +        doTestTEHeaderUnknown("unknown, chunked");
    +    }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown04() throws Exception {
    +        doTestTEHeaderUnknown("void");
    +    }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown05() throws Exception {
    +        doTestTEHeaderUnknown("void, chunked");
    +    }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown06() throws Exception {
    +        doTestTEHeaderUnknown("void, identity");
    +    }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown07() throws Exception {
    +        doTestTEHeaderUnknown("identity, void");
    +    }
    +
    +
    +    private void doTestTEHeaderUnknown(String headerValue) throws Exception {
    +        Tomcat tomcat = getTomcatInstance();
    +
    +        // No file system docBase required
    +        Context ctx = tomcat.addContext("", null);
    +
    +        // Add servlet
    +        Tomcat.addServlet(ctx, "TesterServlet", new TesterServlet(false));
    +        ctx.addServletMappingDecoded("/foo", "TesterServlet");
    +
    +        tomcat.start();
    +
    +        String request =
    +                "GET /foo HTTP/1.1" + SimpleHttpClient.CRLF +
    +                "Host: localhost:" + getPort() + SimpleHttpClient.CRLF +
    +                "Transfer-Encoding: " + headerValue + SimpleHttpClient.CRLF +
    +                SimpleHttpClient.CRLF;
    +
    +        Client client = new Client(tomcat.getConnector().getLocalPort());
    +        client.setRequest(new String[] {request});
    +
    +        client.connect();
    +        client.processRequest(false);
    +
    +        Assert.assertTrue(client.isResponse501());
    +    }
     }
    
  • webapps/docs/changelog.xml+6 0 modified
    @@ -192,6 +192,12 @@
             the empty token is at the start, middle or end of the list of tokens.
             (markt)
           </fix>
    +      <fix>
    +        Remove support for the <code>identity</code> transfer encoding. The
    +        inclusion of this encoding in RFC 2616 was an error that was corrected
    +        in 2001. Requests using this transfer encoding will now receive a 501
    +        response. (markt)
    +      </fix>
         </changelog>
       </subsection>
       <subsection name="Jasper">
    
45d70a86a901

Remove support for the identity T-E header value

https://github.com/apache/tomcatMark ThomasMay 10, 2021via ghsa
3 files changed · +78 31
  • java/org/apache/coyote/http11/Http11Processor.java+2 6 modified
    @@ -212,11 +212,8 @@ private void addInputFilter(InputFilter[] inputFilters, String encodingName) {
     
             // Parsing trims and converts to lower case.
     
    -        if (encodingName.equals("identity")) {
    -            // Skip
    -        } else if (encodingName.equals("chunked")) {
    -            inputBuffer.addActiveFilter
    -                (inputFilters[Constants.CHUNKED_FILTER]);
    +        if (encodingName.equals("chunked")) {
    +            inputBuffer.addActiveFilter(inputFilters[Constants.CHUNKED_FILTER]);
                 contentDelimitation = true;
             } else {
                 for (int i = pluggableFilterIndex; i < inputFilters.length; i++) {
    @@ -759,7 +756,6 @@ private void prepareRequest() throws IOException {
                     List<String> encodingNames = new ArrayList<>();
                     if (TokenList.parseTokenList(headers.values("transfer-encoding"), encodingNames)) {
                         for (String encodingName : encodingNames) {
    -                        // "identity" codings are ignored
                             addInputFilter(inputFilters, encodingName);
                         }
                     } else {
    
  • test/org/apache/coyote/http11/TestHttp11Processor.java+70 25 modified
    @@ -253,31 +253,6 @@ private void doTestWithTEChunked(boolean withCL) throws Exception {
         }
     
     
    -    @Test
    -    public void testWithTEIdentity() throws Exception {
    -        getTomcatInstanceTestWebapp(false, true);
    -
    -        String request =
    -            "POST /test/echo-params.jsp HTTP/1.1" + SimpleHttpClient.CRLF +
    -            "Host: any" + SimpleHttpClient.CRLF +
    -            "Transfer-encoding: identity" + SimpleHttpClient.CRLF +
    -            "Content-Length: 9" + SimpleHttpClient.CRLF +
    -            "Content-Type: application/x-www-form-urlencoded" +
    -                    SimpleHttpClient.CRLF +
    -            "Connection: close" + SimpleHttpClient.CRLF +
    -                SimpleHttpClient.CRLF +
    -            "test=data";
    -
    -        Client client = new Client(getPort());
    -        client.setRequest(new String[] {request});
    -
    -        client.connect();
    -        client.processRequest();
    -        Assert.assertTrue(client.isResponse200());
    -        Assert.assertTrue(client.getResponseBody().contains("test - data"));
    -    }
    -
    -
         @Test
         public void testWithTESavedRequest() throws Exception {
             getTomcatInstanceTestWebapp(false, true);
    @@ -1859,4 +1834,74 @@ public void onError(Throwable throwable) {
                 // NO-OP
             }
         }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown01() throws Exception {
    +        doTestTEHeaderUnknown("identity");
    +    }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown02() throws Exception {
    +        doTestTEHeaderUnknown("identity, chunked");
    +    }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown03() throws Exception {
    +        doTestTEHeaderUnknown("unknown, chunked");
    +    }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown04() throws Exception {
    +        doTestTEHeaderUnknown("void");
    +    }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown05() throws Exception {
    +        doTestTEHeaderUnknown("void, chunked");
    +    }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown06() throws Exception {
    +        doTestTEHeaderUnknown("void, identity");
    +    }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown07() throws Exception {
    +        doTestTEHeaderUnknown("identity, void");
    +    }
    +
    +
    +    private void doTestTEHeaderUnknown(String headerValue) throws Exception {
    +        Tomcat tomcat = getTomcatInstance();
    +
    +        // No file system docBase required
    +        Context ctx = tomcat.addContext("", null);
    +
    +        // Add servlet
    +        Tomcat.addServlet(ctx, "TesterServlet", new TesterServlet(false));
    +        ctx.addServletMappingDecoded("/foo", "TesterServlet");
    +
    +        tomcat.start();
    +
    +        String request =
    +                "GET /foo HTTP/1.1" + SimpleHttpClient.CRLF +
    +                "Host: localhost:" + getPort() + SimpleHttpClient.CRLF +
    +                "Transfer-Encoding: " + headerValue + SimpleHttpClient.CRLF +
    +                SimpleHttpClient.CRLF;
    +
    +        Client client = new Client(tomcat.getConnector().getLocalPort());
    +        client.setRequest(new String[] {request});
    +
    +        client.connect();
    +        client.processRequest(false);
    +
    +        Assert.assertTrue(client.isResponse501());
    +    }
     }
    
  • webapps/docs/changelog.xml+6 0 modified
    @@ -218,6 +218,12 @@
             the empty token is at the start, middle or end of the list of tokens.
             (markt)
           </fix>
    +      <fix>
    +        Remove support for the <code>identity</code> transfer encoding. The
    +        inclusion of this encoding in RFC 2616 was an error that was corrected
    +        in 2001. Requests using this transfer encoding will now receive a 501
    +        response. (markt)
    +      </fix>
         </changelog>
       </subsection>
       <subsection name="Jasper">
    
3202703e6d63

Remove support for the identity T-E header value

https://github.com/apache/tomcatMark ThomasMay 10, 2021via ghsa
3 files changed · +78 31
  • java/org/apache/coyote/http11/Http11Processor.java+2 6 modified
    @@ -454,11 +454,8 @@ private void addInputFilter(InputFilter[] inputFilters, String encodingName) {
     
             // Parsing trims and converts to lower case.
     
    -        if (encodingName.equals("identity")) {
    -            // Skip
    -        } else if (encodingName.equals("chunked")) {
    -            inputBuffer.addActiveFilter
    -                (inputFilters[Constants.CHUNKED_FILTER]);
    +        if (encodingName.equals("chunked")) {
    +            inputBuffer.addActiveFilter(inputFilters[Constants.CHUNKED_FILTER]);
                 contentDelimitation = true;
             } else {
                 for (int i = pluggableFilterIndex; i < inputFilters.length; i++) {
    @@ -1001,7 +998,6 @@ private void prepareRequest() throws IOException {
                     List<String> encodingNames = new ArrayList<>();
                     if (TokenList.parseTokenList(headers.values("transfer-encoding"), encodingNames)) {
                         for (String encodingName : encodingNames) {
    -                        // "identity" codings are ignored
                             addInputFilter(inputFilters, encodingName);
                         }
                     } else {
    
  • test/org/apache/coyote/http11/TestHttp11Processor.java+70 25 modified
    @@ -255,31 +255,6 @@ private void doTestWithTEChunked(boolean withCL) throws Exception {
         }
     
     
    -    @Test
    -    public void testWithTEIdentity() throws Exception {
    -        getTomcatInstanceTestWebapp(false, true);
    -
    -        String request =
    -            "POST /test/echo-params.jsp HTTP/1.1" + SimpleHttpClient.CRLF +
    -            "Host: any" + SimpleHttpClient.CRLF +
    -            "Transfer-encoding: identity" + SimpleHttpClient.CRLF +
    -            "Content-Length: 9" + SimpleHttpClient.CRLF +
    -            "Content-Type: application/x-www-form-urlencoded" +
    -                    SimpleHttpClient.CRLF +
    -            "Connection: close" + SimpleHttpClient.CRLF +
    -                SimpleHttpClient.CRLF +
    -            "test=data";
    -
    -        Client client = new Client(getPort());
    -        client.setRequest(new String[] {request});
    -
    -        client.connect();
    -        client.processRequest();
    -        Assert.assertTrue(client.isResponse200());
    -        Assert.assertTrue(client.getResponseBody().contains("test - data"));
    -    }
    -
    -
         @Test
         public void testWithTESavedRequest() throws Exception {
             getTomcatInstanceTestWebapp(false, true);
    @@ -1875,4 +1850,74 @@ public void onError(Throwable throwable) {
                 // NO-OP
             }
         }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown01() throws Exception {
    +        doTestTEHeaderUnknown("identity");
    +    }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown02() throws Exception {
    +        doTestTEHeaderUnknown("identity, chunked");
    +    }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown03() throws Exception {
    +        doTestTEHeaderUnknown("unknown, chunked");
    +    }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown04() throws Exception {
    +        doTestTEHeaderUnknown("void");
    +    }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown05() throws Exception {
    +        doTestTEHeaderUnknown("void, chunked");
    +    }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown06() throws Exception {
    +        doTestTEHeaderUnknown("void, identity");
    +    }
    +
    +
    +    @Test
    +    public void testTEHeaderUnknown07() throws Exception {
    +        doTestTEHeaderUnknown("identity, void");
    +    }
    +
    +
    +    private void doTestTEHeaderUnknown(String headerValue) throws Exception {
    +        Tomcat tomcat = getTomcatInstance();
    +
    +        // No file system docBase required
    +        Context ctx = tomcat.addContext("", null);
    +
    +        // Add servlet
    +        Tomcat.addServlet(ctx, "TesterServlet", new TesterServlet(false));
    +        ctx.addServletMappingDecoded("/foo", "TesterServlet");
    +
    +        tomcat.start();
    +
    +        String request =
    +                "GET /foo HTTP/1.1" + SimpleHttpClient.CRLF +
    +                "Host: localhost:" + getPort() + SimpleHttpClient.CRLF +
    +                "Transfer-Encoding: " + headerValue + SimpleHttpClient.CRLF +
    +                SimpleHttpClient.CRLF;
    +
    +        Client client = new Client(tomcat.getConnector().getLocalPort());
    +        client.setRequest(new String[] {request});
    +
    +        client.connect();
    +        client.processRequest(false);
    +
    +        Assert.assertTrue(client.isResponse501());
    +    }
     }
    
  • webapps/docs/changelog.xml+6 0 modified
    @@ -206,6 +206,12 @@
             the empty token is at the start, middle or end of the list of tokens.
             (markt)
           </fix>
    +      <fix>
    +        Remove support for the <code>identity</code> transfer encoding. The
    +        inclusion of this encoding in RFC 2616 was an error that was corrected
    +        in 2001. Requests using this transfer encoding will now receive a 501
    +        response. (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

38

News mentions

0

No linked articles in our index yet.