This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/9.0.x by this push:
new 2714a7ed51 Hardening: Use SecureRandom to generate Sec-WebSocket-Key
2714a7ed51 is described below
commit 2714a7ed519e9a6dff86fb506b4132fcd6f907b4
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 00d4546b5b..e0015c6d77 100644
--- a/java/org/apache/tomcat/websocket/Util.java
+++ b/java/org/apache/tomcat/websocket/Util.java
@@ -136,7 +136,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
@@ -155,8 +155,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 1b069f28e7..1402af48f4 100644
--- a/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
+++ b/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
@@ -578,7 +578,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 12bd393bb0..07429ed19a 100644
--- a/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
+++ b/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
@@ -42,7 +42,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;
@@ -89,7 +88,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);
@@ -770,8 +768,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 8771ab380a..b578fb61ee 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 3fbc19ecb4..fe8328a2fc 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 6783b6d70b..aa03553df5 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -186,6 +186,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.