Apache Tomcat: DoS via malformed HTTP/2 PRIORITY_UPDATE frame
Description
Improper Input Validation vulnerability in Apache Tomcat. Incorrect error handling for some invalid HTTP priority headers resulted in incomplete clean-up of the failed request which created a memory leak. A large number of such requests could trigger an OutOfMemoryException resulting in a denial of service.
This issue affects Apache Tomcat: from 9.0.76 through 9.0.102, from 10.1.10 through 10.1.39, from 11.0.0-M2 through 11.0.5. The following versions were EOL at the time the CVE was created but are known to be affected: 8.5.90 though 8.5.100.
Users are recommended to upgrade to version 9.0.104, 10.1.40 or 11.0.6 which fix the issue.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Improper HTTP priority header validation in Apache Tomcat causes a memory leak, leading to denial of service via OutOfMemoryError.
Vulnerability
Description
CVE-2025-31650 is an Improper Input Validation vulnerability in Apache Tomcat that arises from incorrect error handling for certain malformed HTTP priority headers. When Tomcat encounters these invalid headers, the error handling mechanism does not properly clean up the partially processed request, causing a memory leak. Repeated exploitation can exhaust the Java heap, triggering an OutOfMemoryError and resulting in a denial of service [1][2][3].
Attack
Vector and Prerequisites
The vulnerability is exploitable remotely over HTTP by sending crafted requests with invalid priority headers. No authentication is required, and the attack does not need special network position as long as the attacker can reach the Tomcat server. The affected versions include Tomcat 9.0.76 through 9.0.102, 10.1.10 through 10.1.39, and 11.0.0-M2 through 11.0.5. Additionally, the end-of-life (EOL) branch 8.5.90 through 8.5.100 is known to be affected [1][2][4].
Impact
An attacker can continuously send a large number of requests with invalid priority headers, causing the server's memory to steadily increase. Once the JVM heap is exhausted, the Tomcat instance becomes unresponsive to legitimate requests, effectively denying service. The vulnerability does not allow code execution or data exfiltration; it is a pure denial-of-service scenario.
Mitigation and
Advisory
The Apache Tomcat project has released patched versions: 9.0.104, 10.1.40, and 11.0.6. Users running affected versions should upgrade immediately. For the EOL 8.5.x branch, no official fix is provided, and users are strongly advised to migrate to a supported branch. No workarounds are documented; the vulnerability is remedied by upgrading to the fixed releases [1][2][4].
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.apache.tomcat:tomcat-coyoteMaven | >= 9.0.76, < 9.0.104 | 9.0.104 |
org.apache.tomcat:tomcat-coyoteMaven | >= 10.1.10, < 10.1.40 | 10.1.40 |
org.apache.tomcat:tomcat-coyoteMaven | >= 11.0.0-M2, < 11.0.6 | 11.0.6 |
org.apache.tomcat.embed:tomcat-embed-coreMaven | >= 9.0.76, < 9.0.104 | 9.0.104 |
org.apache.tomcat.embed:tomcat-embed-coreMaven | >= 10.1.10, < 10.1.40 | 10.1.40 |
org.apache.tomcat.embed:tomcat-embed-coreMaven | >= 11.0.0-M2, < 11.0.6 | 11.0.6 |
org.apache.tomcat:tomcat-coyoteMaven | >= 8.5.0, <= 8.5.100 | — |
org.apache.tomcat.embed:tomcat-embed-coreMaven | >= 8.5.0, <= 8.5.100 | — |
Affected products
56- osv-coords54 versionspkg:apk/chainguard/camunda-zeebe-8.6pkg:apk/chainguard/camunda-zeebe-8.6-compatpkg:apk/chainguard/thingsboardpkg:apk/chainguard/thingsboard-tb-js-executorpkg:apk/chainguard/thingsboard-tb-mqtt-transportpkg:apk/chainguard/thingsboard-tb-nodepkg:apk/chainguard/thingsboard-tb-web-uipkg:apk/wolfi/thingsboardpkg:apk/wolfi/thingsboard-tb-js-executorpkg:apk/wolfi/thingsboard-tb-mqtt-transportpkg:apk/wolfi/thingsboard-tb-nodepkg:apk/wolfi/thingsboard-tb-web-uipkg:bitnami/tomcatpkg:maven/org.apache.tomcat.embed/tomcat-embed-corepkg:maven/org.apache.tomcat/tomcat-coyotepkg:rpm/almalinux/tomcatpkg:rpm/almalinux/tomcat9pkg:rpm/almalinux/tomcat9-admin-webappspkg:rpm/almalinux/tomcat9-docs-webapppkg:rpm/almalinux/tomcat9-el-3.0-apipkg:rpm/almalinux/tomcat9-jsp-2.3-apipkg:rpm/almalinux/tomcat9-libpkg:rpm/almalinux/tomcat9-servlet-4.0-apipkg:rpm/almalinux/tomcat9-webappspkg:rpm/almalinux/tomcat-admin-webappspkg:rpm/almalinux/tomcat-docs-webapppkg:rpm/almalinux/tomcat-el-3.0-apipkg:rpm/almalinux/tomcat-jsp-2.3-apipkg:rpm/almalinux/tomcat-libpkg:rpm/almalinux/tomcat-servlet-4.0-apipkg:rpm/almalinux/tomcat-webappspkg:rpm/opensuse/tomcat10&distro=openSUSE%20Leap%2015.6pkg:rpm/opensuse/tomcat&distro=openSUSE%20Leap%2015.6pkg:rpm/suse/tomcat10&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP5-ESPOSpkg:rpm/suse/tomcat10&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP5-LTSSpkg:rpm/suse/tomcat10&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Web%20and%20Scripting%2015%20SP6pkg:rpm/suse/tomcat10&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Web%20and%20Scripting%2015%20SP7pkg:rpm/suse/tomcat10&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP5-LTSSpkg:rpm/suse/tomcat10&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP5pkg:rpm/suse/tomcat&distro=SUSE%20Enterprise%20Storage%207.1pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP3-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP4-ESPOSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP4-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP5-ESPOSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015%20SP5-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Web%20and%20Scripting%2015%20SP6pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Web%20and%20Scripting%2015%20SP7pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP3-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP4-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%2015%20SP5-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP3pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP4pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015%20SP5pkg:rpm/suse/tomcat&distro=SUSE%20Manager%20Server%204.3
< 8.6.15-r1+ 53 more
- (no CPE)range: < 8.6.15-r1
- (no CPE)range: < 8.6.15-r1
- (no CPE)range: < 4.0.1-r1
- (no CPE)range: < 4.0.1-r1
- (no CPE)range: < 4.0.1-r1
- (no CPE)range: < 4.0.1-r1
- (no CPE)range: < 4.0.1-r1
- (no CPE)range: < 4.0.1-r1
- (no CPE)range: < 4.0.1-r1
- (no CPE)range: < 4.0.1-r1
- (no CPE)range: < 4.0.1-r1
- (no CPE)range: < 4.0.1-r1
- (no CPE)range: >= 9.0.76, < 9.0.104
- (no CPE)range: >= 9.0.76, < 9.0.104
- (no CPE)range: >= 9.0.76, < 9.0.104
- (no CPE)range: < 1:9.0.87-1.el8_10.4
- (no CPE)range: < 1:9.0.87-5.el10_0.1
- (no CPE)range: < 1:9.0.87-5.el10_0.1
- (no CPE)range: < 1:9.0.87-5.el10_0.1
- (no CPE)range: < 1:9.0.87-5.el10_0.1
- (no CPE)range: < 1:9.0.87-5.el10_0.1
- (no CPE)range: < 1:9.0.87-5.el10_0.1
- (no CPE)range: < 1:9.0.87-5.el10_0.1
- (no CPE)range: < 1:9.0.87-5.el10_0.1
- (no CPE)range: < 1:9.0.87-1.el8_10.4
- (no CPE)range: < 1:9.0.87-1.el8_10.4
- (no CPE)range: < 1:9.0.87-1.el8_10.4
- (no CPE)range: < 1:9.0.87-1.el8_10.4
- (no CPE)range: < 1:9.0.87-1.el8_10.4
- (no CPE)range: < 1:9.0.87-1.el8_10.4
- (no CPE)range: < 1:9.0.87-1.el8_10.4
- (no CPE)range: < 10.1.40-150200.5.40.1
- (no CPE)range: < 9.0.104-150200.81.1
- (no CPE)range: < 10.1.40-150200.5.40.1
- (no CPE)range: < 10.1.40-150200.5.40.1
- (no CPE)range: < 10.1.40-150200.5.40.1
- (no CPE)range: < 10.1.40-150200.5.40.1
- (no CPE)range: < 10.1.40-150200.5.40.1
- (no CPE)range: < 10.1.40-150200.5.40.1
- (no CPE)range: < 9.0.104-150200.81.1
- (no CPE)range: < 9.0.104-150200.81.1
- (no CPE)range: < 9.0.104-150200.81.1
- (no CPE)range: < 9.0.104-150200.81.1
- (no CPE)range: < 9.0.104-150200.81.1
- (no CPE)range: < 9.0.104-150200.81.1
- (no CPE)range: < 9.0.104-150200.81.1
- (no CPE)range: < 9.0.104-150200.81.1
- (no CPE)range: < 9.0.104-150200.81.1
- (no CPE)range: < 9.0.104-150200.81.1
- (no CPE)range: < 9.0.104-150200.81.1
- (no CPE)range: < 9.0.104-150200.81.1
- (no CPE)range: < 9.0.104-150200.81.1
- (no CPE)range: < 9.0.104-150200.81.1
- (no CPE)range: < 9.0.104-150200.81.1
- Apache Software Foundation/Apache Tomcatv5Range: 9.0.76
Patches
98cc3b8fb3f2dImprove handling of unexpected errors during HTTP/2 processing
3 files changed · +12 −0
java/org/apache/coyote/http2/Http2UpgradeHandler.java+8 −0 modified@@ -48,6 +48,7 @@ import org.apache.coyote.http2.Http2Parser.Output; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.util.ExceptionUtils; import org.apache.tomcat.util.http.MimeHeaders; import org.apache.tomcat.util.http.parser.Priority; import org.apache.tomcat.util.log.UserDataHelper; @@ -442,6 +443,13 @@ public SocketState upgradeDispatch(SocketEvent status) { log.debug(sm.getString("upgradeHandler.ioerror", connectionId), ioe); } close(); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + if (log.isDebugEnabled()) { + log.debug(sm.getString("upgradeHandler.throwable", connectionId), t); + } + // Unexpected errors close the connection. + close(); } if (log.isTraceEnabled()) {
java/org/apache/coyote/http2/LocalStrings.properties+1 −0 modified@@ -166,6 +166,7 @@ upgradeHandler.stream.error=Connection [{0}], Stream [{1}] Closed due to error upgradeHandler.stream.even=A new remote stream ID of [{0}] was requested but all remote streams must use odd identifiers upgradeHandler.stream.notWritable=Connection [{0}], Stream [{1}], This stream is in state [{2}] and is not writable upgradeHandler.stream.old=A new remote stream ID of [{0}] was requested but the most recent stream was [{1}] +upgradeHandler.throwable=Connection [{0}] upgradeHandler.tooManyRemoteStreams=The client attempted to use more than [{0}] active streams upgradeHandler.tooMuchOverhead=Connection [{0}], Too much overhead so the connection will be closed upgradeHandler.unexpectedAck=Connection [{0}], Stream [{1}], A settings acknowledgement was received when not expected
webapps/docs/changelog.xml+3 −0 modified@@ -134,6 +134,9 @@ <bug>69614</bug>: HTTP/2 priority frames with an invalid priority field value should be ignored. (markt) </fix> + <fix> + Improve handling of unexpected errors during HTTP/2 processing. (markt) + </fix> </changelog> </subsection> </section>
ded0285b96b4Improve handling of unexpected errors during HTTP/2 processing
3 files changed · +12 −0
java/org/apache/coyote/http2/Http2UpgradeHandler.java+8 −0 modified@@ -48,6 +48,7 @@ import org.apache.coyote.http2.Http2Parser.Output; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.util.ExceptionUtils; import org.apache.tomcat.util.http.MimeHeaders; import org.apache.tomcat.util.http.parser.Priority; import org.apache.tomcat.util.log.UserDataHelper; @@ -441,6 +442,13 @@ public SocketState upgradeDispatch(SocketEvent status) { log.debug(sm.getString("upgradeHandler.ioerror", connectionId), ioe); } close(); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + if (log.isDebugEnabled()) { + log.debug(sm.getString("upgradeHandler.throwable", connectionId), t); + } + // Unexpected errors close the connection. + close(); } if (log.isTraceEnabled()) {
java/org/apache/coyote/http2/LocalStrings.properties+1 −0 modified@@ -166,6 +166,7 @@ upgradeHandler.stream.error=Connection [{0}], Stream [{1}] Closed due to error upgradeHandler.stream.even=A new remote stream ID of [{0}] was requested but all remote streams must use odd identifiers upgradeHandler.stream.notWritable=Connection [{0}], Stream [{1}], This stream is in state [{2}] and is not writable upgradeHandler.stream.old=A new remote stream ID of [{0}] was requested but the most recent stream was [{1}] +upgradeHandler.throwable=Connection [{0}] upgradeHandler.tooManyRemoteStreams=The client attempted to use more than [{0}] active streams upgradeHandler.tooMuchOverhead=Connection [{0}], Too much overhead so the connection will be closed upgradeHandler.unexpectedAck=Connection [{0}], Stream [{1}], A settings acknowledgement was received when not expected
webapps/docs/changelog.xml+3 −0 modified@@ -140,6 +140,9 @@ <bug>69614</bug>: HTTP/2 priority frames with an invalid priority field value should be ignored. (markt) </fix> + <fix> + Improve handling of unexpected errors during HTTP/2 processing. (markt) + </fix> </changelog> </subsection> <subsection name="Jasper">
b7674782679eImprove handling of unexpected errors during HTTP/2 processing
3 files changed · +12 −0
java/org/apache/coyote/http2/Http2UpgradeHandler.java+8 −0 modified@@ -47,6 +47,7 @@ import org.apache.coyote.http2.Http2Parser.Output; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.util.ExceptionUtils; import org.apache.tomcat.util.http.MimeHeaders; import org.apache.tomcat.util.http.parser.Priority; import org.apache.tomcat.util.log.UserDataHelper; @@ -439,6 +440,13 @@ public SocketState upgradeDispatch(SocketEvent status) { log.debug(sm.getString("upgradeHandler.ioerror", connectionId), ioe); } close(); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + if (log.isDebugEnabled()) { + log.debug(sm.getString("upgradeHandler.throwable", connectionId), t); + } + // Unexpected errors close the connection. + close(); } if (log.isTraceEnabled()) {
java/org/apache/coyote/http2/LocalStrings.properties+1 −0 modified@@ -160,6 +160,7 @@ upgradeHandler.stream.error=Connection [{0}], Stream [{1}] Closed due to error upgradeHandler.stream.even=A new remote stream ID of [{0}] was requested but all remote streams must use odd identifiers upgradeHandler.stream.notWritable=Connection [{0}], Stream [{1}], This stream is in state [{2}] and is not writable upgradeHandler.stream.old=A new remote stream ID of [{0}] was requested but the most recent stream was [{1}] +upgradeHandler.throwable=Connection [{0}] upgradeHandler.tooManyRemoteStreams=The client attempted to use more than [{0}] active streams upgradeHandler.tooMuchOverhead=Connection [{0}], Too much overhead so the connection will be closed upgradeHandler.unexpectedAck=Connection [{0}], Stream [{1}], A settings acknowledgement was received when not expected
webapps/docs/changelog.xml+3 −0 modified@@ -134,6 +134,9 @@ <bug>69614</bug>: HTTP/2 priority frames with an invalid priority field value should be ignored. (markt) </fix> + <fix> + Improve handling of unexpected errors during HTTP/2 processing. (markt) + </fix> </changelog> </subsection> </section>
1eef1dc459c4Additional fix for BZ 69614
1 file changed · +6 −0
java/org/apache/coyote/http2/Stream.java+6 −0 modified@@ -456,6 +456,12 @@ public final void emitHeader(String name, String value) throws HpackException { setIncremental(p.getIncremental()); } catch (IOException ioe) { // Not possible with StringReader + } catch (IllegalArgumentException iae) { + // Invalid priority header field values should be ignored + if (log.isTraceEnabled()) { + log.trace(sm.getString("http2Parser.processFramePriorityUpdate.invalid", getConnectionId(), + getIdAsString()), iae); + } } break; }
b98e74f517b3Additional fix for BZ 69614
1 file changed · +6 −0
java/org/apache/coyote/http2/Stream.java+6 −0 modified@@ -456,6 +456,12 @@ public final void emitHeader(String name, String value) throws HpackException { setIncremental(p.getIncremental()); } catch (IOException ioe) { // Not possible with StringReader + } catch (IllegalArgumentException iae) { + // Invalid priority header field values should be ignored + if (log.isTraceEnabled()) { + log.trace(sm.getString("http2Parser.processFramePriorityUpdate.invalid", getConnectionId(), + getIdAsString()), iae); + } } break; }
f619e6a05029Additional fix for BZ 69614
1 file changed · +6 −0
java/org/apache/coyote/http2/Stream.java+6 −0 modified@@ -450,6 +450,12 @@ public final void emitHeader(String name, String value) throws HpackException { setIncremental(p.getIncremental()); } catch (IOException ioe) { // Not possible with StringReader + } catch (IllegalArgumentException iae) { + // Invalid priority header field values should be ignored + if (log.isTraceEnabled()) { + log.trace(sm.getString("http2Parser.processFramePriorityUpdate.invalid", getConnectionId(), + getIdAsString()), iae); + } } break; }
40ae788c2e64Fix BZ 69614 - invalid priority field values should be ignored
4 files changed · +46 −7
java/org/apache/coyote/http2/Http2Parser.java+16 −7 modified@@ -477,15 +477,24 @@ protected void readPriorityUpdateFrame(int payloadSize, ByteBuffer buffer) throw ByteArrayInputStream bais = new ByteArrayInputStream(payload, 4, payloadSize - 4); Reader r = new BufferedReader(new InputStreamReader(bais, StandardCharsets.US_ASCII)); - Priority p = Priority.parsePriority(r); - if (log.isTraceEnabled()) { - log.trace(sm.getString("http2Parser.processFramePriorityUpdate.debug", connectionId, - Integer.toString(prioritizedStreamID), Integer.toString(p.getUrgency()), - Boolean.valueOf(p.getIncremental()))); - } + try { + Priority p = Priority.parsePriority(r); - output.priorityUpdate(prioritizedStreamID, p); + if (log.isTraceEnabled()) { + log.trace(sm.getString("http2Parser.processFramePriorityUpdate.debug", connectionId, + Integer.toString(prioritizedStreamID), Integer.toString(p.getUrgency()), + Boolean.valueOf(p.getIncremental()))); + } + + output.priorityUpdate(prioritizedStreamID, p); + } catch (IllegalArgumentException iae) { + // Priority frames with invalid priority field values should be ignored + if (log.isTraceEnabled()) { + log.trace(sm.getString("http2Parser.processFramePriorityUpdate.invalid", connectionId, + Integer.toString(prioritizedStreamID)), iae); + } + } }
java/org/apache/coyote/http2/LocalStrings.properties+1 −0 modified@@ -77,6 +77,7 @@ http2Parser.processFrameHeaders.decodingDataLeft=Data left over after HPACK deco http2Parser.processFrameHeaders.decodingFailed=There was an error during the HPACK decoding of HTTP headers http2Parser.processFrameHeaders.payload=Connection [{0}], Stream [{1}], Processing headers payload of size [{2}] http2Parser.processFramePriorityUpdate.debug=Connection [{0}], Stream [{1}], Urgency [{2}], Incremental [{3}] +http2Parser.processFramePriorityUpdate.invalid=Connection [{0}], Stream [{1}], Priority Update frame with invalid priority field value http2Parser.processFramePriorityUpdate.streamZero=Connection [{0}], Priority update frame received to prioritize stream zero http2Parser.processFramePushPromise=Connection [{0}], Stream [{1}], Push promise frames should not be sent by the client http2Parser.processFrameSettings.ackWithNonZeroPayload=Settings frame received with the ACK flag set and payload present
test/org/apache/coyote/http2/TestRfc9218.java+25 −0 modified@@ -17,6 +17,7 @@ package org.apache.coyote.http2; import java.io.IOException; +import java.nio.charset.StandardCharsets; import org.junit.Assert; import org.junit.Test; @@ -146,6 +147,9 @@ public void testPriority() throws Exception { // 19 - 7021 body left // 21 - 6143 body left + // BZ 69614 - invalid priority update frames should be ignored + sendInvalidPriorityUpdate(17); + // Re-order the priorities sendPriorityUpdate(17, 2, true); @@ -191,4 +195,25 @@ public void testPriority() throws Exception { ioe.printStackTrace(); } } + + + private void sendInvalidPriorityUpdate(int streamId) throws IOException { + byte[] payload = "u=1:i".getBytes(StandardCharsets.US_ASCII); + + byte[] priorityUpdateFrame = new byte[13 + payload.length]; + + // length + ByteUtil.setThreeBytes(priorityUpdateFrame, 0, 4 + payload.length); + // type + priorityUpdateFrame[3] = FrameType.PRIORITY_UPDATE.getIdByte(); + // Stream ID + ByteUtil.set31Bits(priorityUpdateFrame, 5, 0); + + // Payload + ByteUtil.set31Bits(priorityUpdateFrame, 9, streamId); + System.arraycopy(payload, 0, priorityUpdateFrame, 13, payload.length); + + os.write(priorityUpdateFrame); + os.flush(); + } }
webapps/docs/changelog.xml+4 −0 modified@@ -130,6 +130,10 @@ <bug>69607</bug>: Allow failed initialization of MD5. Based on code submitted by Shivam Verma. (remm) </fix> + <fix> + <bug>69614</bug>: HTTP/2 priority frames with an invalid priority field + value should be ignored. (markt) + </fix> </changelog> </subsection> </section>
cba1a0fe1289Fix BZ 69614 - invalid priority field values should be ignored
4 files changed · +46 −7
java/org/apache/coyote/http2/Http2Parser.java+16 −7 modified@@ -477,15 +477,24 @@ protected void readPriorityUpdateFrame(int payloadSize, ByteBuffer buffer) throw ByteArrayInputStream bais = new ByteArrayInputStream(payload, 4, payloadSize - 4); Reader r = new BufferedReader(new InputStreamReader(bais, StandardCharsets.US_ASCII)); - Priority p = Priority.parsePriority(r); - if (log.isTraceEnabled()) { - log.trace(sm.getString("http2Parser.processFramePriorityUpdate.debug", connectionId, - Integer.toString(prioritizedStreamID), Integer.toString(p.getUrgency()), - Boolean.valueOf(p.getIncremental()))); - } + try { + Priority p = Priority.parsePriority(r); - output.priorityUpdate(prioritizedStreamID, p); + if (log.isTraceEnabled()) { + log.trace(sm.getString("http2Parser.processFramePriorityUpdate.debug", connectionId, + Integer.toString(prioritizedStreamID), Integer.toString(p.getUrgency()), + Boolean.valueOf(p.getIncremental()))); + } + + output.priorityUpdate(prioritizedStreamID, p); + } catch (IllegalArgumentException iae) { + // Priority frames with invalid priority field values should be ignored + if (log.isTraceEnabled()) { + log.trace(sm.getString("http2Parser.processFramePriorityUpdate.invalid", connectionId, + Integer.toString(prioritizedStreamID)), iae); + } + } }
java/org/apache/coyote/http2/LocalStrings.properties+1 −0 modified@@ -77,6 +77,7 @@ http2Parser.processFrameHeaders.decodingDataLeft=Data left over after HPACK deco http2Parser.processFrameHeaders.decodingFailed=There was an error during the HPACK decoding of HTTP headers http2Parser.processFrameHeaders.payload=Connection [{0}], Stream [{1}], Processing headers payload of size [{2}] http2Parser.processFramePriorityUpdate.debug=Connection [{0}], Stream [{1}], Urgency [{2}], Incremental [{3}] +http2Parser.processFramePriorityUpdate.invalid=Connection [{0}], Stream [{1}], Priority Update frame with invalid priority field value http2Parser.processFramePriorityUpdate.streamZero=Connection [{0}], Priority update frame received to prioritize stream zero http2Parser.processFramePushPromise=Connection [{0}], Stream [{1}], Push promise frames should not be sent by the client http2Parser.processFrameSettings.ackWithNonZeroPayload=Settings frame received with the ACK flag set and payload present
test/org/apache/coyote/http2/TestRfc9218.java+25 −0 modified@@ -17,6 +17,7 @@ package org.apache.coyote.http2; import java.io.IOException; +import java.nio.charset.StandardCharsets; import org.junit.Assert; import org.junit.Test; @@ -146,6 +147,9 @@ public void testPriority() throws Exception { // 19 - 7021 body left // 21 - 6143 body left + // BZ 69614 - invalid priority update frames should be ignored + sendInvalidPriorityUpdate(17); + // Re-order the priorities sendPriorityUpdate(17, 2, true); @@ -191,4 +195,25 @@ public void testPriority() throws Exception { ioe.printStackTrace(); } } + + + private void sendInvalidPriorityUpdate(int streamId) throws IOException { + byte[] payload = "u=1:i".getBytes(StandardCharsets.US_ASCII); + + byte[] priorityUpdateFrame = new byte[13 + payload.length]; + + // length + ByteUtil.setThreeBytes(priorityUpdateFrame, 0, 4 + payload.length); + // type + priorityUpdateFrame[3] = FrameType.PRIORITY_UPDATE.getIdByte(); + // Stream ID + ByteUtil.set31Bits(priorityUpdateFrame, 5, 0); + + // Payload + ByteUtil.set31Bits(priorityUpdateFrame, 9, streamId); + System.arraycopy(payload, 0, priorityUpdateFrame, 13, payload.length); + + os.write(priorityUpdateFrame); + os.flush(); + } }
webapps/docs/changelog.xml+4 −0 modified@@ -130,6 +130,10 @@ <bug>69607</bug>: Allow failed initialization of MD5. Based on code submitted by Shivam Verma. (remm) </fix> + <fix> + <bug>69614</bug>: HTTP/2 priority frames with an invalid priority field + value should be ignored. (markt) + </fix> </changelog> </subsection> </section>
75554da2fc55Fix BZ 69614 - invalid priority field values should be ignored
4 files changed · +46 −7
java/org/apache/coyote/http2/Http2Parser.java+16 −7 modified@@ -460,15 +460,24 @@ protected void readPriorityUpdateFrame(int payloadSize, ByteBuffer buffer) throw ByteArrayInputStream bais = new ByteArrayInputStream(payload, 4, payloadSize - 4); Reader r = new BufferedReader(new InputStreamReader(bais, StandardCharsets.US_ASCII)); - Priority p = Priority.parsePriority(r); - if (log.isTraceEnabled()) { - log.trace(sm.getString("http2Parser.processFramePriorityUpdate.debug", connectionId, - Integer.toString(prioritizedStreamID), Integer.toString(p.getUrgency()), - Boolean.valueOf(p.getIncremental()))); - } + try { + Priority p = Priority.parsePriority(r); - output.priorityUpdate(prioritizedStreamID, p); + if (log.isTraceEnabled()) { + log.trace(sm.getString("http2Parser.processFramePriorityUpdate.debug", connectionId, + Integer.toString(prioritizedStreamID), Integer.toString(p.getUrgency()), + Boolean.valueOf(p.getIncremental()))); + } + + output.priorityUpdate(prioritizedStreamID, p); + } catch (IllegalArgumentException iae) { + // Priority frames with invalid priority field values should be ignored + if (log.isTraceEnabled()) { + log.trace(sm.getString("http2Parser.processFramePriorityUpdate.invalid", connectionId, + Integer.toString(prioritizedStreamID)), iae); + } + } }
java/org/apache/coyote/http2/LocalStrings.properties+1 −0 modified@@ -77,6 +77,7 @@ http2Parser.processFrameHeaders.decodingDataLeft=Data left over after HPACK deco http2Parser.processFrameHeaders.decodingFailed=There was an error during the HPACK decoding of HTTP headers http2Parser.processFrameHeaders.payload=Connection [{0}], Stream [{1}], Processing headers payload of size [{2}] http2Parser.processFramePriorityUpdate.debug=Connection [{0}], Stream [{1}], Urgency [{2}], Incremental [{3}] +http2Parser.processFramePriorityUpdate.invalid=Connection [{0}], Stream [{1}], Priority Update frame with invalid priority field value http2Parser.processFramePriorityUpdate.streamZero=Connection [{0}], Priority update frame received to prioritize stream zero http2Parser.processFramePushPromise=Connection [{0}], Stream [{1}], Push promise frames should not be sent by the client http2Parser.processFrameSettings.ackWithNonZeroPayload=Settings frame received with the ACK flag set and payload present
test/org/apache/coyote/http2/TestRfc9218.java+25 −0 modified@@ -17,6 +17,7 @@ package org.apache.coyote.http2; import java.io.IOException; +import java.nio.charset.StandardCharsets; import org.junit.Assert; import org.junit.Test; @@ -146,6 +147,9 @@ public void testPriority() throws Exception { // 19 - 7021 body left // 21 - 6143 body left + // BZ 69614 - invalid priority update frames should be ignored + sendInvalidPriorityUpdate(17); + // Re-order the priorities sendPriorityUpdate(17, 2, true); @@ -191,4 +195,25 @@ public void testPriority() throws Exception { ioe.printStackTrace(); } } + + + private void sendInvalidPriorityUpdate(int streamId) throws IOException { + byte[] payload = "u=1:i".getBytes(StandardCharsets.US_ASCII); + + byte[] priorityUpdateFrame = new byte[13 + payload.length]; + + // length + ByteUtil.setThreeBytes(priorityUpdateFrame, 0, 4 + payload.length); + // type + priorityUpdateFrame[3] = FrameType.PRIORITY_UPDATE.getIdByte(); + // Stream ID + ByteUtil.set31Bits(priorityUpdateFrame, 5, 0); + + // Payload + ByteUtil.set31Bits(priorityUpdateFrame, 9, streamId); + System.arraycopy(payload, 0, priorityUpdateFrame, 13, payload.length); + + os.write(priorityUpdateFrame); + os.flush(); + } }
webapps/docs/changelog.xml+4 −0 modified@@ -136,6 +136,10 @@ <bug>69607</bug>: Allow failed initialization of MD5. Based on code submitted by Shivam Verma. (remm) </fix> + <fix> + <bug>69614</bug>: HTTP/2 priority frames with an invalid priority field + value should be ignored. (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
17- github.com/advisories/GHSA-3p2h-wqq4-wf4hghsaADVISORY
- lists.apache.org/thread/j6zzk0y3yym9pzfzkq5vcyxzz0yzh826ghsavendor-advisoryWEB
- nvd.nist.gov/vuln/detail/CVE-2025-31650ghsaADVISORY
- www.openwall.com/lists/oss-security/2025/04/28/2ghsaWEB
- github.com/apache/tomcat/commit/1eef1dc459c45f1e421d8bd25ef340fc1cc34edcghsaWEB
- github.com/apache/tomcat/commit/40ae788c2e64d018b4e58cd4210bb96434d0100dghsaWEB
- github.com/apache/tomcat/commit/75554da2fc5574862510ae6f0d7b3d78937f1d40ghsaWEB
- github.com/apache/tomcat/commit/8cc3b8fb3f2d8d4d6a757e014f19d1fafa948a60ghsaWEB
- github.com/apache/tomcat/commit/b7674782679e1514a0d154166b1d04d38aaac4a9ghsaWEB
- github.com/apache/tomcat/commit/b98e74f517b36929f4208506e5adad22cb767baaghsaWEB
- github.com/apache/tomcat/commit/cba1a0fe1289ee7f5dd46c61c38d1e1ac5437bffghsaWEB
- github.com/apache/tomcat/commit/ded0285b96b4d3f5560dfc8856ad5ec4a9b50ba9ghsaWEB
- github.com/apache/tomcat/commit/f619e6a05029538886d5a9d987925d573b5bb8c2ghsaWEB
- lists.debian.org/debian-lts-announce/2025/07/msg00009.htmlghsaWEB
- tomcat.apache.org/security-10.htmlghsaWEB
- tomcat.apache.org/security-11.htmlghsaWEB
- tomcat.apache.org/security-9.htmlghsaWEB
News mentions
0No linked articles in our index yet.