(tomcat) branch 10.1.x updated: Hardening: Use SecureRandom to generate Sec-WebSocket-Key

[email protected]
Newsgroups gmane.comp.jakarta.tomcat.devel
Message-ID <178765223163.2174811.15886416051613428529@gitbox3-he-fi.apache.org>
This is an automated email from the ASF dual-hosted git repository.

markt-asf pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/10.1.x by this push:
     new f4507c5ad0 Hardening: Use SecureRandom to generate Sec-WebSocket-Key
f4507c5ad0 is described below

commit f4507c5ad015ed0de268c0bae76917e885f42c4f
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 c21dbc94b9..d9550ab423 100644
--- a/java/org/apache/tomcat/websocket/Util.java
+++ b/java/org/apache/tomcat/websocket/Util.java
@@ -137,7 +137,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
@@ -156,8 +156,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 1e3782063f..9dd87a6ea2 100644
--- a/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
+++ b/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
@@ -579,7 +579,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 4a80443c64..940b22d78c 100644
--- a/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
+++ b/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
@@ -43,7 +43,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;
@@ -91,7 +90,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);
@@ -784,8 +782,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 571755d295..d51a2242b5 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -162,6 +162,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.