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">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]