CVE-2020-13935
Description
The payload length in a WebSocket frame was not correctly validated in Apache Tomcat 10.0.0-M1 to 10.0.0-M6, 9.0.0.M1 to 9.0.36, 8.5.0 to 8.5.56 and 7.0.27 to 7.0.104. Invalid payload lengths could trigger an infinite loop. Multiple requests with invalid payload lengths could lead to a denial of service.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Apache Tomcat WebSocket payload length validation flaw leads to infinite loop and denial of service (DoS).
The vulnerability resides in the WebSocket frame processing logic of Apache Tomcat. The payload length field in a WebSocket frame is not properly validated, allowing an attacker to send a frame with an invalid payload length that triggers an infinite loop in the server. This issue affects multiple Tomcat versions: 7.0.27 to 7.0.104, 8.5.0 to 8.5.56, 9.0.0.M1 to 9.0.36, and 10.0.0-M1 to 10.0.0-M6 [1][2][3][4].
An attacker can exploit this vulnerability by sending a specially crafted WebSocket frame with an invalid payload length to a vulnerable Tomcat server. No authentication is required, and the attack can be performed over a network connection where WebSocket communication is enabled. By sending multiple such requests, the attacker can cause the server to enter an infinite loop repeatedly, consuming CPU resources and leading to a denial of service [1].
The impact of successful exploitation is a denial of service condition, which can render the Tomcat server unresponsive. This can affect the availability of web applications hosted on the server.
Apache Tomcat has released fixes for this vulnerability. Users should upgrade to Tomcat 7.0.105 or later, 8.5.57 or later, 9.0.37 or later, or 10.0.0-M7 or later. Note that Tomcat 7.0.x has reached end of life and no further security fixes will be provided; users are strongly advised to migrate to a supported branch [1].
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.
| Package | Affected versions | Patched versions |
|---|---|---|
org.apache.tomcat:tomcatMaven | >= 10.0.0-M1, < 10.0.0-M7 | 10.0.0-M7 |
org.apache.tomcat:tomcatMaven | >= 9.0.0.M1, < 9.0.37 | 9.0.37 |
org.apache.tomcat:tomcatMaven | >= 8.5.0, < 8.5.57 | 8.5.57 |
org.apache.tomcat:tomcatMaven | >= 7.0.27, < 7.0.105 | 7.0.105 |
Affected products
32- osv-coords31 versionspkg:bitnami/tomcatpkg:maven/org.apache.tomcat/tomcatpkg:rpm/opensuse/tomcat10&distro=openSUSE%20Tumbleweedpkg:rpm/opensuse/tomcat&distro=openSUSE%20Leap%2015.1pkg:rpm/opensuse/tomcat&distro=openSUSE%20Leap%2015.2pkg:rpm/opensuse/tomcat&distro=openSUSE%20Tumbleweedpkg:rpm/suse/tomcat&distro=HPE%20Helion%20OpenStack%208pkg:rpm/suse/tomcat&distro=SUSE%20Enterprise%20Storage%205pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015-ESPOSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20High%20Performance%20Computing%2015-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Web%20and%20Scripting%2015%20SP1pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Web%20and%20Scripting%2015%20SP2pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%2012%20SP2-BCLpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%2012%20SP2-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%2012%20SP3-BCLpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%2012%20SP3-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%2012%20SP4-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%2012%20SP5pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%2012%20SP5-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%2015-LTSSpkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2012%20SP2pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2012%20SP3pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2012%20SP4pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2012%20SP5pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%20for%20SAP%20Applications%2015pkg:rpm/suse/tomcat&distro=SUSE%20Linux%20Enterprise%20Server%20LTSS%20Extended%20Security%2012%20SP5pkg:rpm/suse/tomcat&distro=SUSE%20OpenStack%20Cloud%207pkg:rpm/suse/tomcat&distro=SUSE%20OpenStack%20Cloud%208pkg:rpm/suse/tomcat&distro=SUSE%20OpenStack%20Cloud%209pkg:rpm/suse/tomcat&distro=SUSE%20OpenStack%20Cloud%20Crowbar%208pkg:rpm/suse/tomcat&distro=SUSE%20OpenStack%20Cloud%20Crowbar%209
>= 7.0.27, < 7.0.105+ 30 more
- (no CPE)range: >= 7.0.27, < 7.0.105
- (no CPE)range: >= 10.0.0-M1, < 10.0.0-M7
- (no CPE)range: < 10.1.14-1.1
- (no CPE)range: < 9.0.36-lp151.3.27.1
- (no CPE)range: < 9.0.36-lp152.2.4.1
- (no CPE)range: < 9.0.43-8.1
- (no CPE)range: < 8.0.53-29.37.1
- (no CPE)range: < 8.0.53-29.37.1
- (no CPE)range: < 9.0.36-3.65.2
- (no CPE)range: < 9.0.36-3.65.2
- (no CPE)range: < 9.0.36-4.41.2
- (no CPE)range: < 9.0.36-3.6.1
- (no CPE)range: < 8.0.53-29.37.1
- (no CPE)range: < 8.0.53-29.37.1
- (no CPE)range: < 8.0.53-29.37.1
- (no CPE)range: < 8.0.53-29.37.1
- (no CPE)range: < 9.0.36-3.45.1
- (no CPE)range: < 9.0.36-3.45.1
- (no CPE)range: < 9.0.115-3.160.1
- (no CPE)range: < 9.0.36-3.65.2
- (no CPE)range: < 8.0.53-29.37.1
- (no CPE)range: < 8.0.53-29.37.1
- (no CPE)range: < 9.0.36-3.45.1
- (no CPE)range: < 9.0.36-3.45.1
- (no CPE)range: < 9.0.36-3.65.2
- (no CPE)range: < 9.0.115-3.160.1
- (no CPE)range: < 8.0.53-29.37.1
- (no CPE)range: < 8.0.53-29.37.1
- (no CPE)range: < 9.0.36-3.45.1
- (no CPE)range: < 8.0.53-29.37.1
- (no CPE)range: < 9.0.36-3.45.1
Patches
54c04982870d6Fix BZ 64563 - additional payload length validation
2 files changed · +7 −0
java/org/apache/catalina/websocket/LocalStrings.properties+1 −0 modified@@ -14,6 +14,7 @@ # limitations under the License. frame.eos=The end of the stream was reached before the expected number of payload bytes could be read +frame.invalidLength=An invalid payload length was specified frame.invalidUtf8=A sequence of bytes was received that did not represent valid UTF-8 frame.notMasked=The client frame was not masked but all client frames must be masked frame.readEos=The end of the stream was reached when trying to read the first byte of a new WebSocket frame
java/org/apache/catalina/websocket/WsFrame.java+6 −0 modified@@ -84,6 +84,12 @@ private WsFrame(byte first, blockingRead(processor, extended); payloadLength = Conversions.byteArrayToLong(extended); } + // The most significant bit of those 8 bytes is required to be zero + // (see RFC 6455, section 5.2). If the most significant bit is set, + // the resulting payload length will be negative so test for that. + if (payloadLength < 0) { + throw new IOException(sm.getString("frame.invalidLength")); + } if (isControl()) { if (payloadLength > 125) {
12d715676038Fix BZ 64563 - additional payload length validation
3 files changed · +16 −0
java/org/apache/tomcat/websocket/LocalStrings.properties+1 −0 modified@@ -71,6 +71,7 @@ wsFrame.noContinuation=A new message was started when a continuation frame was e wsFrame.notMasked=The client frame was not masked but all client frames must be masked wsFrame.oneByteCloseCode=The client sent a close frame with a single byte payload which is not valid wsFrame.partialHeaderComplete=WebSocket frame received. fin [{0}], rsv [{1}], OpCode [{2}], payload length [{3}] +wsFrame.payloadMsbInvalid=An invalid WebSocket frame was received - the most significant bit of a 64-bit payload was illegally set wsFrame.sessionClosed=The client data cannot be processed because the session has already been closed wsFrame.suspendRequested=Suspend of the message receiving has already been requested. wsFrame.textMessageTooBig=The decoded text message was too big for the output buffer and the endpoint does not support partial messages
java/org/apache/tomcat/websocket/WsFrameBase.java+7 −0 modified@@ -261,6 +261,13 @@ private boolean processRemainingHeader() throws IOException { } else if (payloadLength == 127) { payloadLength = byteArrayToLong(inputBuffer.array(), inputBuffer.arrayOffset() + inputBuffer.position(), 8); + // The most significant bit of those 8 bytes is required to be zero + // (see RFC 6455, section 5.2). If the most significant bit is set, + // the resulting payload length will be negative so test for that. + if (payloadLength < 0) { + throw new WsIOException( + new CloseReason(CloseCodes.PROTOCOL_ERROR, sm.getString("wsFrame.payloadMsbInvalid"))); + } inputBuffer.position(inputBuffer.position() + 8); } if (Util.isControl(opCode)) {
webapps/docs/changelog.xml+8 −0 modified@@ -123,6 +123,14 @@ </fix> </changelog> </subsection> + <subsection name="WebSocket"> + <changelog> + <fix> + <bug>64563</bug>: Add additional validation of payload length for + WebSocket messages. (markt) + </fix> + </changelog> + </subsection> <subsection name="Other"> <changelog> <fix>
1c1c77b0efb6Fix BZ 64563 - additional payload length validation
3 files changed · +16 −0
java/org/apache/tomcat/websocket/LocalStrings.properties+1 −0 modified@@ -71,6 +71,7 @@ wsFrame.noContinuation=A new message was started when a continuation frame was e wsFrame.notMasked=The client frame was not masked but all client frames must be masked wsFrame.oneByteCloseCode=The client sent a close frame with a single byte payload which is not valid wsFrame.partialHeaderComplete=WebSocket frame received. fin [{0}], rsv [{1}], OpCode [{2}], payload length [{3}] +wsFrame.payloadMsbInvalid=An invalid WebSocket frame was received - the most significant bit of a 64-bit payload was illegally set wsFrame.sessionClosed=The client data cannot be processed because the session has already been closed wsFrame.suspendRequested=Suspend of the message receiving has already been requested. wsFrame.textMessageTooBig=The decoded text message was too big for the output buffer and the endpoint does not support partial messages
java/org/apache/tomcat/websocket/WsFrameBase.java+7 −0 modified@@ -261,6 +261,13 @@ private boolean processRemainingHeader() throws IOException { } else if (payloadLength == 127) { payloadLength = byteArrayToLong(inputBuffer.array(), inputBuffer.arrayOffset() + inputBuffer.position(), 8); + // The most significant bit of those 8 bytes is required to be zero + // (see RFC 6455, section 5.2). If the most significant bit is set, + // the resulting payload length will be negative so test for that. + if (payloadLength < 0) { + throw new WsIOException( + new CloseReason(CloseCodes.PROTOCOL_ERROR, sm.getString("wsFrame.payloadMsbInvalid"))); + } inputBuffer.position(inputBuffer.position() + 8); } if (Util.isControl(opCode)) {
webapps/docs/changelog.xml+8 −0 modified@@ -138,6 +138,14 @@ </fix> </changelog> </subsection> + <subsection name="WebSocket"> + <changelog> + <fix> + <bug>64563</bug>: Add additional validation of payload length for + WebSocket messages. (markt) + </fix> + </changelog> + </subsection> <subsection name="Web Applications"> <changelog> <update>
40fa74c74822Fix BZ 64563 - additional payload length validation
3 files changed · +16 −0
java/org/apache/tomcat/websocket/LocalStrings.properties+1 −0 modified@@ -71,6 +71,7 @@ wsFrame.noContinuation=A new message was started when a continuation frame was e wsFrame.notMasked=The client frame was not masked but all client frames must be masked wsFrame.oneByteCloseCode=The client sent a close frame with a single byte payload which is not valid wsFrame.partialHeaderComplete=WebSocket frame received. fin [{0}], rsv [{1}], OpCode [{2}], payload length [{3}] +wsFrame.payloadMsbInvalid=An invalid WebSocket frame was received - the most significant bit of a 64-bit payload was illegally set wsFrame.sessionClosed=The client data cannot be processed because the session has already been closed wsFrame.suspendRequested=Suspend of the message receiving has already been requested. wsFrame.textMessageTooBig=The decoded text message was too big for the output buffer and the endpoint does not support partial messages
java/org/apache/tomcat/websocket/WsFrameBase.java+7 −0 modified@@ -261,6 +261,13 @@ private boolean processRemainingHeader() throws IOException { } else if (payloadLength == 127) { payloadLength = byteArrayToLong(inputBuffer.array(), inputBuffer.arrayOffset() + inputBuffer.position(), 8); + // The most significant bit of those 8 bytes is required to be zero + // (see RFC 6455, section 5.2). If the most significant bit is set, + // the resulting payload length will be negative so test for that. + if (payloadLength < 0) { + throw new WsIOException( + new CloseReason(CloseCodes.PROTOCOL_ERROR, sm.getString("wsFrame.payloadMsbInvalid"))); + } inputBuffer.position(inputBuffer.position() + 8); } if (Util.isControl(opCode)) {
webapps/docs/changelog.xml+8 −0 modified@@ -127,6 +127,14 @@ </fix> </changelog> </subsection> + <subsection name="WebSocket"> + <changelog> + <fix> + <bug>64563</bug>: Add additional validation of payload length for + WebSocket messages. (markt) + </fix> + </changelog> + </subsection> <subsection name="Other"> <changelog> <fix>
f9f75c14678bFix BZ 64563 - additional payload length validation
3 files changed · +12 −0
java/org/apache/tomcat/websocket/LocalStrings.properties+1 −0 modified@@ -64,6 +64,7 @@ wsFrame.noContinuation=A new message was started when a continuation frame was e wsFrame.notMasked=The client frame was not masked but all client frames must be masked wsFrame.oneByteCloseCode=The client sent a close frame with a single byte payload which is not valid wsFrame.partialHeaderComplete=WebSocket frame received. fin [{0}], rsv [{1}], OpCode [{2}], payload length [{3}] +wsFrame.payloadMsbInvalid=An invalid WebSocket frame was received - the most significant bit of a 64-bit payload was illegally set wsFrame.sessionClosed=The client data cannot be processed because the session has already been closed wsFrame.textMessageTooBig=The decoded text message was too big for the output buffer and the endpoint does not support partial messages wsFrame.wrongRsv=The client frame set the reserved bits to [{0}] for a message with opCode [{1}] which was not supported by this endpoint
java/org/apache/tomcat/websocket/WsFrameBase.java+7 −0 modified@@ -256,6 +256,13 @@ private boolean processRemainingHeader() throws IOException { readPos += 2; } else if (payloadLength == 127) { payloadLength = byteArrayToLong(inputBuffer, readPos, 8); + // The most significant bit of those 8 bytes is required to be zero + // (see RFC 6455, section 5.2). If the most significant bit is set, + // the resulting payload length will be negative so test for that. + if (payloadLength < 0) { + throw new WsIOException( + new CloseReason(CloseCodes.PROTOCOL_ERROR, sm.getString("wsFrame.payloadMsbInvalid"))); + } readPos += 8; } if (Util.isControl(opCode)) {
webapps/docs/changelog.xml+4 −0 modified@@ -105,6 +105,10 @@ Include the target URL in the log message when a WebSocket connection fails. (markt) </add> + <fix> + <bug>64563</bug>: Add additional validation of payload length for + WebSocket messages. (markt) + </fix> </changelog> </subsection> <subsection name="Other">
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
32- lists.opensuse.org/opensuse-security-announce/2020-07/msg00084.htmlghsavendor-advisoryx_refsource_SUSEWEB
- lists.opensuse.org/opensuse-security-announce/2020-07/msg00088.htmlghsavendor-advisoryx_refsource_SUSEWEB
- github.com/advisories/GHSA-m7jv-hq7h-mq7cghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2020-13935ghsaADVISORY
- usn.ubuntu.com/4448-1/mitrevendor-advisoryx_refsource_UBUNTU
- usn.ubuntu.com/4596-1/mitrevendor-advisoryx_refsource_UBUNTU
- www.debian.org/security/2020/dsa-4727ghsavendor-advisoryx_refsource_DEBIANWEB
- github.com/apache/tomcat/commit/12d715676038efbf9c728af10163f8277fc019d5ghsaWEB
- github.com/apache/tomcat/commit/1c1c77b0efb667cea80b532440b44cea1dc427c3ghsaWEB
- github.com/apache/tomcat/commit/40fa74c74822711ab878079d0a69f7357926723dghsaWEB
- github.com/apache/tomcat/commit/4c04982870d6e730c38e21e58fb653b7cf723784ghsaWEB
- github.com/apache/tomcat/commit/f9f75c14678b68633f79030ddf4ff827f014cc84ghsaWEB
- kc.mcafee.com/corporate/indexghsax_refsource_CONFIRMWEB
- lists.apache.org/thread.html/r4e5d3c09f4dd2923191e972408b40fb8b42dbff0bc7904d44b651e50%40%3Cusers.tomcat.apache.org%3Emitremailing-listx_refsource_MLIST
- lists.apache.org/thread.html/r4e5d3c09f4dd2923191e972408b40fb8b42dbff0bc7904d44b651e50@%3Cusers.tomcat.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rd48c72bd3255bda87564d4da3791517c074d94f8a701f93b85752651%40%3Cannounce.tomcat.apache.org%3Eghsax_refsource_MISCWEB
- lists.debian.org/debian-lts-announce/2020/07/msg00017.htmlghsamailing-listx_refsource_MLISTWEB
- security.netapp.com/advisory/ntap-20200724-0003ghsaWEB
- security.netapp.com/advisory/ntap-20200724-0003/mitrex_refsource_CONFIRM
- tomcat.apache.org/security-10.htmlghsaWEB
- tomcat.apache.org/security-7.htmlghsaWEB
- tomcat.apache.org/security-8.htmlghsaWEB
- tomcat.apache.org/security-9.htmlghsaWEB
- usn.ubuntu.com/4448-1ghsaWEB
- usn.ubuntu.com/4596-1ghsaWEB
- www.oracle.com//security-alerts/cpujul2021.htmlghsax_refsource_MISCWEB
- www.oracle.com/security-alerts/cpuApr2021.htmlghsax_refsource_MISCWEB
- www.oracle.com/security-alerts/cpuapr2022.htmlghsax_refsource_MISCWEB
- www.oracle.com/security-alerts/cpujan2021.htmlghsax_refsource_MISCWEB
- www.oracle.com/security-alerts/cpujan2022.htmlghsax_refsource_MISCWEB
- www.oracle.com/security-alerts/cpuoct2020.htmlghsax_refsource_MISCWEB
- www.oracle.com/security-alerts/cpuoct2021.htmlghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.