CVE-2026-41293
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Apache Tomcat is an open-source implementation of the Jakarta Servlet, Jakarta Server Pages, Jakarta Expression Language, Jakarta WebSocket, Jakarta Annotations, and Jakarta Authentication specifications, providing a pure Java HTTP web server environment for running Java code. It is one of the most widely used Java application servers.
A low-severity vulnerability (CVE-2026-41293) has been identified in Apache Tomcat where HTTP/2 request header field names and field values decoded from HPACK are not validated against the character sets required by RFC 9113 and RFC 7230. An attacker can therefore place arbitrary byte values, including control characters and other non-token / non-field-vchar bytes, into header names and values that are then exposed unchanged to the application through the Servlet API.
Per OWASP: Information Exposure occurs when an application unintentionally discloses or transmits data in a form that does not match the trust assumptions of downstream consumers. In this case, Servlet-API consumers reasonably assume that values returned by HttpServletRequest.getHeader(...) conform to the HTTP specification; without validation, those consumers can be fed bytes that the protocol forbids, leading to log injection, mis-routing, or other unexpected application behaviour. Unlike the HTTP/1.1 chunked-encoding case, this defect does not enable HTTP request smuggling because HTTP/2 framing already delimits requests; the hazard is downstream application logic that trusts header content to be specification-compliant.
This issue affects versions 8.5.0 through 8.5.100, 9.0.0.M1 through 9.0.117, 10.1.0-M1 through 10.1.54, and 11.0.0-M1 through 11.0.21 of Apache Tomcat.
Details
Module Info
- Product: Apache Tomcat
- Affected packages: tomcat-coyote, tomcat-embed-core
- Affected versions: >=8.5.0 <=8.5.100, >=9.0.0.M1 <=9.0.117, >=10.1.0-M1 <=10.1.54, >=11.0.0-M1 <=11.0.21
- GitHub repository: https://github.com/apache/tomcat
- Published packages:
- Package manager: Maven
- Fixed in:
- NES for Apache Tomcat
- Apache Tomcat 11.0.22, 10.1.55, 9.0.118 (OSS)
Vulnerability Info
The vulnerability exists in the HPACK decode path used by Tomcat's HTTP/2 implementation, primarily in HpackDecoder.java and HPackHuffman.java. Prior to the fix, HpackDecoder.readHpackString(...) and HPackHuffman.decode(...) accepted every byte produced by HPACK / Huffman decoding into the resulting field name or field value without any check that the resulting characters were a valid token (for field names) or field-vchar / field-content (for field values) per RFC 7230 §3.2.6 and RFC 9113 §8.2.
Pre-fix code in HpackDecoder.java:
private String readHpackString(ByteBuffer buffer) throws HpackException {
...
if (huffman) {
return readHuffmanString(length, buffer);
}
StringBuilder stringBuilder = new StringBuilder(length);
for (int i = 0; i < length; ++i) {
stringBuilder.append((char) buffer.get());
}
return stringBuilder.toString();
}
The only character-level enforcement performed downstream was a single uppercase-name rejection in Stream.emitHeader(...):
// Header names must be lowercase
if (!name.toLowerCase(Locale.US).equals(name)) {
headerException =
new StreamException(sm.getString("stream.header.case", ...),
Http2Error.PROTOCOL_ERROR, getIdAsInt());
return;
}
Nothing rejected non-token characters in names, non-field-vchar bytes at the start or end of values, non-field-content bytes inside values, or empty values.
The fix wires field-name vs field-value awareness through the HPACK decode path. readHpackString and readHuffmanString gain an isFieldName flag, and each decoded character is validated against HttpParser.isToken(...) (for names) and the new HttpParser.isFieldVChar(...) / HttpParser.isFieldContent(...) helpers (for values). A matching four-argument HPackHuffman.decode(ByteBuffer, int, StringBuilder, boolean isFieldName) overload performs the same per-character checks on Huffman-encoded names and values. Http2Parser.readHeaderPayload(...) translates any IllegalArgumentException raised by the decoder into a StreamException with Http2Error.PROTOCOL_ERROR, so the offending HTTP/2 stream is reset before the malformed header can reach the application. The now-redundant uppercase-name check in Stream.emitHeader(...) is removed because the HPACK decoder enforces it on every character.
Mitigation
Only recent versions of Apache Tomcat are community-supported. Older versions (8.5.x and earlier) will not receive any updates to address this issue. NES for Tomcat includes an update to 8.5.x to address this issue. For more information, see here.
Users of the affected components should apply one of the following mitigations:
- Upgrade to a patched version of Apache Tomcat.
- Leverage a commercial support partner like HeroDevs for post-EOL security support.