VYPR
Critical severityNVD Advisory· Published May 9, 2023· Updated Jan 28, 2025

Improper Neutralization of Invalid Characters in Data Attribute Names in org.xwiki.commons:xwiki-commons-xml

CVE-2023-31126

Description

XWiki Commons XML HTML sanitizer allows XSS via invalid data attributes in versions 14.6-rc-1 to 14.10.3.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

XWiki Commons XML HTML sanitizer allows XSS via invalid data attributes in versions 14.6-rc-1 to 14.10.3.

The HTML sanitizer in org.xwiki.commons:xwiki-commons-xml, introduced in version 14.6-rc-1, fails to properly validate data attribute names. The sanitizer uses a regex pattern DATA_ATTR to check if an attribute is allowed, but the pattern used .find() instead of .matches(), allowing arbitrary characters after a valid prefix. This enables injection of malicious HTML attributes such as data-x/onmouseover="alert('XSS')" [1][2].

An attacker can exploit this by crafting XWiki syntax links or other content that includes a data attribute with invalid characters. For example, [[Link>>https://XWiki.example.com||data-x/onmouseover="alert('XSS1')"]] will execute JavaScript when a user hovers over the link. No authentication is required as long as the attacker can create or modify content that is rendered by XWiki [3].

Successful exploitation results in Cross-Site Scripting (XSS) in the victim's browser. If the victim has programming rights, the attacker may escalate to server-side code execution, compromising confidentiality, integrity, and availability of the XWiki instance [3].

The vulnerability is patched in XWiki 14.10.4 and 15.0 RC1 by changing the regex validation from .find() to .matches() to ensure data attribute names contain only allowed characters [2]. There are no known workarounds; upgrading is required [3].

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.xwiki.commons:xwiki-commons-xmlMaven
>= 14.6-rc-1, < 14.10.414.10.4

Affected products

2

Patches

1
0b8e9c45b7e7

XCOMMONS-2606: Properly validate data attributes in SecureHTMLElementSanitizer

https://github.com/xwiki/xwiki-commonsMichael HamannJan 13, 2023via ghsa
2 files changed · +32 2
  • xwiki-commons-core/xwiki-commons-xml/src/main/java/org/xwiki/xml/internal/html/SecureHTMLElementSanitizer.java+13 2 modified
    @@ -65,7 +65,18 @@ public class SecureHTMLElementSanitizer implements HTMLElementSanitizer, Initial
         static final Pattern ATTR_WHITESPACE =
             Pattern.compile("[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]");
     
    -    static final Pattern DATA_ATTR = Pattern.compile("^data-[\\-\\w.\\u00B7-\\uFFFF]");
    +    /**
    +     * Pattern that matches valid data-attributes.
    +     * <p>
    +     * Following the <a href="https://html.spec.whatwg.org/multipage/dom.html
    +     #embedding-custom-non-visible-data-with-the-data-*-attributes">HTML standard</a>
    +     * this means that the name starts with "data-", has at least one character after the hyphen and is
    +     * <a href="https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible">XML-compatible</a>,
    +     * i.e., matches the <a href="https://www.w3.org/TR/xml/#NT-Name">Name production</a> without ":".
    +     */
    +    static final Pattern DATA_ATTR = Pattern.compile("^data-[A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6"
    +        + "\\u00F8-\\u02ff\\u0370-\\u037d\\u037f-\\u1fff\\u200c\\u200d\\u2070-\\u218f\\u2c00-\\u2fef\\u3001-\\ud7ff"
    +        + "\\uf900-\\ufdcf\\ufdf0-\\ufffd\\x{10000}-\\x{EFFFF}\\-.0-9\\u00b7\\u0300-\\u036f\\u203f-\\u2040]+$");
     
         static final Pattern ARIA_ATTR = Pattern.compile("^aria-[\\-\\w]+$");
     
    @@ -182,7 +193,7 @@ public boolean isAttributeAllowed(String elementName, String attributeName, Stri
             String lowerElement = elementName.toLowerCase();
             String lowerAttribute = attributeName.toLowerCase();
     
    -        if ((DATA_ATTR.matcher(lowerAttribute).find() || ARIA_ATTR.matcher(lowerAttribute).find())
    +        if ((DATA_ATTR.matcher(lowerAttribute).matches() || ARIA_ATTR.matcher(lowerAttribute).matches())
                 && !this.forbidAttributes.contains(lowerAttribute))
             {
                 result = true;
    
  • xwiki-commons-core/xwiki-commons-xml/src/test/java/org/xwiki/xml/internal/html/SecureHTMLElementSanitizerTest.java+19 0 modified
    @@ -23,13 +23,16 @@
     import java.util.Collections;
     
     import org.junit.jupiter.api.Test;
    +import org.junit.jupiter.params.ParameterizedTest;
    +import org.junit.jupiter.params.provider.CsvSource;
     import org.xwiki.test.annotation.BeforeComponent;
     import org.xwiki.test.annotation.ComponentList;
     import org.xwiki.test.junit5.mockito.ComponentTest;
     import org.xwiki.test.junit5.mockito.InjectMockComponents;
     import org.xwiki.test.junit5.mockito.MockComponent;
     import org.xwiki.xml.html.HTMLConstants;
     
    +import static org.junit.jupiter.api.Assertions.assertEquals;
     import static org.junit.jupiter.api.Assertions.assertFalse;
     import static org.junit.jupiter.api.Assertions.assertTrue;
     import static org.mockito.Mockito.when;
    @@ -133,4 +136,20 @@ void restrictedURIs()
             assertFalse(this.secureHTMLElementSanitizer.isAttributeAllowed(HTMLConstants.TAG_A,
                 HTMLConstants.ATTRIBUTE_HREF, "http://example.com"));
         }
    +
    +    @ParameterizedTest
    +    @CsvSource({
    +        "data-, false",
    +        "data-a, true",
    +        "data-x-wiki.test_\u0192, true",
    +        "data-x\u2713, false",
    +        "data-x/test, false",
    +        "data-x>test, false",
    +        "data-x:y, false"
    +    })
    +    void dataAttributes(String attribute, boolean accepted)
    +    {
    +        assertEquals(accepted, this.secureHTMLElementSanitizer.isAttributeAllowed(HTMLConstants.TAG_DIV, attribute,
    +            "hello"));
    +    }
     }
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.