This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch 11.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/11.0.x by this push:
new e8c20f939d Hardening: Use SecureRandom to generate Sec-WebSocket-Key
e8c20f939d is described below
commit e8c20f939d06335252542f743ef42fd8ac12a51a
Author: Mark Thomas <[email protected]>
AuthorDate: Tue Aug 25 11:03:02 2026 +0100
Hardening: Use SecureRandom to generate Sec-WebSocket-Key
---
java/org/apache/tomcat/websocket/Util.java | 6 +++---
java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java | 2 +-
java/org/apache/tomcat/websocket/WsWebSocketContainer.java | 5 +----
test/org/apache/tomcat/websocket/TestUtil.java | 6 +++---
test/org/apache/tomcat/websocket/pojo/TestPojoEndpointBase.java | 2 +-
webapps/docs/changelog.xml | 4 ++++
6 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/java/org/apache/tomcat/websocket/Util.java b/java/org/apache/tomcat/websocket/Util.java
index c775125839..863e8434a2 100644
--- a/java/org/apache/tomcat/websocket/Util.java
+++ b/java/org/apache/tomcat/websocket/Util.java
@@ -127,7 +127,7 @@ public class Util {
}
- static byte[] generateMask() {
+ static byte[] generateRandomBytes(int len) {
// SecureRandom is not thread-safe so need to make sure only one thread
// uses it at a time. In theory, the pool could grow to the same size
// as the number of request processing threads. In reality, it will be
@@ -146,8 +146,8 @@ public class Util {
}
}
- // Generate the mask
- byte[] result = new byte[4];
+ // Generate the random byte array
+ byte[] result = new byte[len];
sr.nextBytes(result);
// Put the SecureRandom back in the poll
diff --git a/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java b/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
index 1f47f77f5e..a179481eec 100644
--- a/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
+++ b/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
@@ -586,7 +586,7 @@ public abstract class WsRemoteEndpointImplBase implements RemoteEndpoint {
byte[] mask;
if (isMasked()) {
- mask = Util.generateMask();
+ mask = Util.generateRandomBytes(4);
} else {
mask = null;
}
diff --git a/java/org/apache/tomcat/websocket/WsWebSocketContainer.java b/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
index e3222f82d8..c16d775a05 100644
--- a/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
+++ b/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
@@ -39,7 +39,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
@@ -85,7 +84,6 @@ public class WsWebSocketContainer implements WebSocketContainer, BackgroundProce
}
private static final StringManager sm = StringManager.getManager(WsWebSocketContainer.class);
- private static final Random RANDOM = new Random();
private static final byte[] CRLF = new byte[] { 13, 10 };
private static final byte[] GET_BYTES = "GET ".getBytes(StandardCharsets.ISO_8859_1);
@@ -777,8 +775,7 @@ public class WsWebSocketContainer implements WebSocketContainer, BackgroundProce
private static String generateWsKeyValue() {
- byte[] keyBytes = new byte[16];
- RANDOM.nextBytes(keyBytes);
+ byte[] keyBytes = Util.generateRandomBytes(16);
return Base64.getEncoder().encodeToString(keyBytes);
}
diff --git a/test/org/apache/tomcat/websocket/TestUtil.java b/test/org/apache/tomcat/websocket/TestUtil.java
index e7a8c59e92..2dc2b7998c 100644
--- a/test/org/apache/tomcat/websocket/TestUtil.java
+++ b/test/org/apache/tomcat/websocket/TestUtil.java
@@ -31,9 +31,9 @@ import org.junit.Test;
public class TestUtil {
- // Used to init SecureRandom prior to running tests
- public static void generateMask() {
- Util.generateMask();
+ // Used to initialise SecureRandom prior to running tests
+ public static void initSecureRandom() {
+ Util.generateRandomBytes(1);
}
@Test
diff --git a/test/org/apache/tomcat/websocket/pojo/TestPojoEndpointBase.java b/test/org/apache/tomcat/websocket/pojo/TestPojoEndpointBase.java
index 739099df9a..16b1ddf5bf 100644
--- a/test/org/apache/tomcat/websocket/pojo/TestPojoEndpointBase.java
+++ b/test/org/apache/tomcat/websocket/pojo/TestPojoEndpointBase.java
@@ -45,7 +45,7 @@ public class TestPojoEndpointBase extends TomcatBaseTest {
@Test
public void testBug54716() throws Exception {
- TestUtil.generateMask();
+ TestUtil.initSecureRandom();
// Set up utility classes
Bug54716 server = new Bug54716();
SingletonConfigurator.setInstance(server);
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index b10dfe2dab..ba711cf248 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -182,6 +182,10 @@
Fix an exception when an automatic Pong response races with the
closing of the WebSocket session. (moritzfl)
</fix>
+ <fix>
+ Harden the WebSocket client and use a <code>SecureRandom</code> when
+ generating the <code>Sec-WebSocket-Key</code> header. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Web applications">
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.