(tomcat) branch main updated: Hardening: Use SecureRandom to generate Sec-WebSocket-Key

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

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


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

commit a42a5db60aab4abeb6677b230b288702d5ae8996
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 198d1ced5a..5ab5edc4f7 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 deb80519fd..2df96fb0fd 100644
--- a/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
+++ b/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
@@ -597,7 +597,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 495ef6c1b7..35b9732fdc 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);
@@ -780,8 +778,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 c0cd1f69ef..5586d49128 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -404,6 +404,10 @@
         closing of the WebSocket session. Pull request <pr>1041</pr> provided by
         moritzfl. (markt)
       </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.