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(); + } }
