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

dashorst pushed a commit to branch wicket-10.x
in repository https://gitbox.apache.org/repos/asf/wicket.git

commit 3cea021af6b296532f30fd869922a9b3b99b4b43
Author: Emond Papegaaij <[email protected]>
AuthorDate: Mon Oct 5 10:53:44 2026 +0200

    Reject '&' in a component id and a markup id
    
    A browser decodes the character references in an attribute before it
    runs the script in it, and for a numeric reference the closing ';' is
    optional. An id written into an event handler attribute without HTML
    escaping could therefore still end its string literal: '&#39' decodes
    to a quote, and '&#41', '&#59' and the like to other characters the
    check rejects. '&' is now rejected along with them.
    
    No such handler is left on this line; '&' is rejected here as well, so
    that the check means the same on 8.x, 9.x and 10.x.
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 .../org/apache/wicket/ComponentIdCharactersTest.java  | 10 +++++-----
 .../src/main/java/org/apache/wicket/Component.java    | 19 +++++++++++--------
 .../java/org/apache/wicket/IMarkupIdGenerator.java    |  4 ++--
 3 files changed, 18 insertions(+), 15 deletions(-)

diff --git 
a/wicket-core-tests/src/test/java/org/apache/wicket/ComponentIdCharactersTest.java
 
b/wicket-core-tests/src/test/java/org/apache/wicket/ComponentIdCharactersTest.java
index 500359cf2e..611800ae8f 100644
--- 
a/wicket-core-tests/src/test/java/org/apache/wicket/ComponentIdCharactersTest.java
+++ 
b/wicket-core-tests/src/test/java/org/apache/wicket/ComponentIdCharactersTest.java
@@ -34,12 +34,12 @@ import org.junit.jupiter.api.Test;
  */
 class ComponentIdCharactersTest extends WicketTestCase
 {
-       private static final String[] INVALID_IDS = { "a'b", "a\"b", "a`b", 
"a\\b", "a;b", "a(b",
-                       "a)b", "a[b", "a]b", "a{b", "a}b", "a<b", "a>b", 
"a\nb", "a\rb", "a\tb", "a\u0000b",
+       private static final String[] INVALID_IDS = { "a'b", "a\"b", "a`b", 
"a\\b", "a;b", "a(b", "a)b",
+                       "a[b", "a]b", "a{b", "a}b", "a<b", "a>b", "a&b", 
"a\nb", "a\rb", "a\tb", "a\u0000b",
                        "a\u2028b", "a\u2029b" };
 
        /** Characters that cannot end a JavaScript string literal are still 
allowed */
-       private static final String VALID_ID = "a 
b&c=d/e+f,g.h-i_j*k!l\u00fcber1";
+       private static final String VALID_ID = "a 
b#c=d/e+f,g.h-i_j*k!l\u00fcber1";
 
        @Test
        void componentIdMayContainOtherCharacters()
@@ -81,8 +81,8 @@ class ComponentIdCharactersTest extends WicketTestCase
        @Test
        void markupIdFromTheMarkupIsChecked()
        {
-               tester.startPage(new MarkupIdPage("a-b_c.d1 e&amp;f"));
-               
assertTrue(tester.getLastResponseAsString().contains("id=\"a-b_c.d1 
e&amp;f\""));
+               tester.startPage(new MarkupIdPage("a-b_c.d1 e#f"));
+               
assertTrue(tester.getLastResponseAsString().contains("id=\"a-b_c.d1 e#f\""));
 
                WicketRuntimeException e = 
assertThrows(WicketRuntimeException.class,
                        () -> tester.startPage(new MarkupIdPage("a&#039;b")));
diff --git a/wicket-core/src/main/java/org/apache/wicket/Component.java 
b/wicket-core/src/main/java/org/apache/wicket/Component.java
index 326544557a..1a344e392a 100644
--- a/wicket-core/src/main/java/org/apache/wicket/Component.java
+++ b/wicket-core/src/main/java/org/apache/wicket/Component.java
@@ -401,10 +401,10 @@ public abstract class Component
        private static final String MARKUP_ID_ATTR_NAME = "id";
 
        /** Characters a component id or a markup id must not contain, see 
{@link #isValidId(String)} */
-       private static final String INVALID_ID_CHARS = "'\"`\\()[]{}<>;";
+       private static final String INVALID_ID_CHARS = "'\"`\\()[]{}<>;&";
 
        private static final String INVALID_ID_MESSAGE =
-               "must not contain quotes, backslashes, brackets, ';' or control 
characters.";
+               "must not contain quotes, backslashes, brackets, ';', '&' or 
control characters.";
 
        /**
         * Meta data key for line precise error logging for the moment of 
addition. Made package private
@@ -769,8 +769,8 @@ public abstract class Component
        /**
         * @return The 'id' attribute from the associated markup tag
         * @throws WicketRuntimeException
-        *             if the id contains a quote, a backslash, a bracket, 
{@code ';'} or a control
-        *             character
+        *             if the id contains a quote, a backslash, a bracket, 
{@code ';'}, {@code '&'} or a
+        *             control character
         */
        public final String getMarkupIdFromMarkup()
        {
@@ -2816,7 +2816,7 @@ public abstract class Component
 
        /**
         * Set markup ID, which must be String or Integer. A String must not 
contain quotes,
-        * backslashes, brackets, {@code ';'} or control characters.
+        * backslashes, brackets, {@code ';'}, {@code '&'} or control 
characters.
         * 
         * @param markupId
         */
@@ -2876,8 +2876,8 @@ public abstract class Component
         * 
         * @param markupId
         *            markup id value or null to clear any previous user 
defined value. It must not
-        *            contain quotes, backslashes, brackets, {@code ';'} or 
control characters, because
-        *            Wicket writes it into the JavaScript it generates.
+        *            contain quotes, backslashes, brackets, {@code ';'}, 
{@code '&'} or control
+        *            characters, because Wicket writes it into the JavaScript 
it generates.
         * @return this for chaining
         */
        public Component setMarkupId(String markupId)
@@ -4302,7 +4302,10 @@ public abstract class Component
         * Checks the characters of a component id or a markup id. Wicket 
writes both into the
         * JavaScript it generates, the markup id as it is and the component id 
as part of an input name,
         * so characters that can end a JavaScript string literal or statement 
are not allowed: quotes,
-        * backslashes, brackets, {@code ';'} and control characters, line 
breaks included.
+        * backslashes, brackets, {@code ';'} and control characters, line 
breaks included. {@code '&'}
+        * is not allowed either: in a script written into an attribute, such 
as an event handler, the
+        * browser decodes a character reference before the script runs, so 
{@code &#39} would end the
+        * literal as well.
         *
         * @param id
         *            the id to check
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/IMarkupIdGenerator.java 
b/wicket-core/src/main/java/org/apache/wicket/IMarkupIdGenerator.java
index da72b3aa9f..4ad2041a28 100644
--- a/wicket-core/src/main/java/org/apache/wicket/IMarkupIdGenerator.java
+++ b/wicket-core/src/main/java/org/apache/wicket/IMarkupIdGenerator.java
@@ -26,8 +26,8 @@ public interface IMarkupIdGenerator
         * Generates markup id for the given component
         * <p>
         * Wicket writes the markup id into the JavaScript it generates, 
without escaping it. A
-        * generated markup id must therefore not contain quotes, backslashes, 
brackets, {@code ';'} or
-        * control characters. An id the component already has, from
+        * generated markup id must therefore not contain quotes, backslashes, 
brackets, {@code ';'},
+        * {@code '&'} or control characters. An id the component already has, 
from
         * {@link Component#setMarkupId(String)} or from the id attribute in 
its markup, has been
         * checked already.
         *

Reply via email to