This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch 
feature/WW-5695-html5-constraint-validation
in repository https://gitbox.apache.org/repos/asf/struts.git

commit c67aa673e9926a6840d1c074161b98275fe0f2f3
Author: Lukasz Lenart <[email protected]>
AuthorDate: Mon Aug 24 20:27:27 2026 +0200

    WW-5695 fix(components): drop \s and \S from the portable-escape allowlist
    
    Java's \s is ASCII-only by default; ECMAScript's is the wider Unicode
    whitespace set (NBSP and friends). ^\S+$ therefore accepted a value
    containing NBSP on the server while the browser's pattern attribute
    rejected it silently - the exact false-true failure this class exists to
    prevent. \d and \w stay allowed: both engines are ASCII-only for those and
    JavaScript never widens them.
    
    Co-Authored-By: Claude Opus 5 <[email protected]>
---
 .../org/apache/struts2/components/EcmaScriptSafeRegex.java    | 11 +++++++++--
 .../apache/struts2/components/EcmaScriptSafeRegexTest.java    |  8 ++++++++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git 
a/core/src/main/java/org/apache/struts2/components/EcmaScriptSafeRegex.java 
b/core/src/main/java/org/apache/struts2/components/EcmaScriptSafeRegex.java
index 523db7eb1..6cc60d512 100644
--- a/core/src/main/java/org/apache/struts2/components/EcmaScriptSafeRegex.java
+++ b/core/src/main/java/org/apache/struts2/components/EcmaScriptSafeRegex.java
@@ -31,8 +31,15 @@ package org.apache.struts2.components;
  */
 public final class EcmaScriptSafeRegex {
 
-    /** Escapes with identical meaning in both engines. */
-    private static final String ALLOWED_ESCAPES = 
"dDwWsSbBnrtf\\.*+?()[]{}|^$/-";
+    /**
+     * Escapes with identical meaning in both engines.
+     * <p>
+     * {@code \s} and {@code \S} are deliberately absent. Java's {@code \s} is 
ASCII-only by default
+     * while ECMAScript's is the wider Unicode set, so {@code ^\S+$} accepts a 
value containing NBSP
+     * on the server and rejects it in the browser. {@code \d} and {@code \w} 
are safe — both engines
+     * are ASCII-only for those, and JavaScript never widens them.
+     */
+    private static final String ALLOWED_ESCAPES = 
"dDwWbBnrtf\\.*+?()[]{}|^$/-";
 
     private EcmaScriptSafeRegex() {
     }
diff --git 
a/core/src/test/java/org/apache/struts2/components/EcmaScriptSafeRegexTest.java 
b/core/src/test/java/org/apache/struts2/components/EcmaScriptSafeRegexTest.java
index ebb8058fa..a895d1337 100644
--- 
a/core/src/test/java/org/apache/struts2/components/EcmaScriptSafeRegexTest.java
+++ 
b/core/src/test/java/org/apache/struts2/components/EcmaScriptSafeRegexTest.java
@@ -72,4 +72,12 @@ public class EcmaScriptSafeRegexTest {
         assertThat(EcmaScriptSafeRegex.isSafe("abc\\")).isFalse();
         assertThat(EcmaScriptSafeRegex.isSafe("[abc")).isFalse();
     }
+
+    @Test
+    public void rejectsWhitespaceClassesWhoseMeaningDiffersBetweenEngines() {
+        // Java's \s is ASCII-only by default; ECMAScript's includes NBSP and 
friends, so
+        // ^\S+$ accepts a value containing NBSP on the server and rejects it 
in the browser
+        assertThat(EcmaScriptSafeRegex.isSafe("^\\S+$")).isFalse();
+        assertThat(EcmaScriptSafeRegex.isSafe("\\s*")).isFalse();
+    }
 }

Reply via email to