From 84db7a9eae8468c0445b15aa806fa7fa806fa0f2 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 8 Sep 2025 14:14:15 +0200
Subject: [PATCH] ws: get a new mask for each new outgoing frame

Reported-by: Calvin Ruocco
Closes #18496

CVE: CVE-2025-10148
Upstream-Status: Backport [https://github.com/curl/curl/commit/84db7a9eae8468c0445b15aa806fa]
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
---
 lib/ws.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/lib/ws.c b/lib/ws.c
index 5bc5ecc..02e0ef0 100644
--- a/lib/ws.c
+++ b/lib/ws.c
@@ -614,6 +614,18 @@ static ssize_t ws_enc_write_head(struct Curl_easy *data,
   enc->payload_remain = enc->payload_len = payload_len;
   ws_enc_info(enc, data, "sending");
 
+    /* 4 bytes random */
+
+  result = Curl_rand(data, (unsigned char *)&enc->mask, sizeof(enc->mask));
+  if(result)
+    return result;
+
+#ifdef DEBUGBUILD
+  if(getenv("CURL_WS_FORCE_ZERO_MASK"))
+    /* force the bit mask to 0x00000000, effectively disabling masking */
+    memset(&enc->mask, 0, sizeof(enc->mask));
+#endif
+
   /* add 4 bytes mask */
   memcpy(&head[hlen], &enc->mask, 4);
   hlen += 4;
@@ -802,14 +814,7 @@ CURLcode Curl_ws_accept(struct Curl_easy *data,
      subprotocol not requested by the client), the client MUST Fail
      the WebSocket Connection. */
 
-  /* 4 bytes random */
-
-  result = Curl_rand(data, (unsigned char *)&ws->enc.mask,
-                     sizeof(ws->enc.mask));
-  if(result)
-    return result;
-  infof(data, "Received 101, switch to WebSocket; mask %02x%02x%02x%02x",
-        ws->enc.mask[0], ws->enc.mask[1], ws->enc.mask[2], ws->enc.mask[3]);
+  infof(data, "Received 101, switch to WebSocket");
 
   /* Install our client writer that decodes WS frames payload */
   result = Curl_cwriter_create(&ws_dec_writer, data, &ws_cw_decode,
-- 
2.50.1

