XWiki Platform vulnerable to stored cross-site scripting in ClassEditSheet page via name parameters
Description
XWiki Platform is a generic wiki platform. Starting in version 5.4.4 and prior to versions 14.4.8, 14.10.4, and 15.0, a stored cross-site scripting vulnerability can be exploited by users with edit rights by adding a AppWithinMinutes.FormFieldCategoryClass class on a page and setting the payload on the page title. Then, any user visiting /xwiki/bin/view/AppWithinMinutes/ClassEditSheet executes the payload. The issue has been patched in XWiki 14.4.8, 14.10.4, and 15.0. As a workaround, update AppWithinMinutes.ClassEditSheet with a patch.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.xwiki.platform:xwiki-platform-appwithinminutes-uiMaven | >= 5.4.4, < 14.4.8 | 14.4.8 |
org.xwiki.platform:xwiki-platform-appwithinminutes-uiMaven | >= 14.5, < 14.10.4 | 14.10.4 |
org.xwiki.platform:xwiki-platform-appwithinminutes-uiMaven | >= 15.0-rc-1, < 15.0 | 15.0 |
Affected products
1- Range: >= 5.4.4, < 14.4.8
Patches
11b87fec1e5b5XWIKI-20365: Improved ClassEditSheet escaping
3 files changed · +118 −3
xwiki-platform-core/xwiki-platform-appwithinminutes/xwiki-platform-appwithinminutes-ui/pom.xml+7 −0 modified@@ -130,5 +130,12 @@ <groupId>org.webjars</groupId> <artifactId>scriptaculous</artifactId> </dependency> + <!-- Test dependencies. --> + <dependency> + <groupId>org.xwiki.platform</groupId> + <artifactId>xwiki-platform-test-page</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> </dependencies> </project>
xwiki-platform-core/xwiki-platform-appwithinminutes/xwiki-platform-appwithinminutes-ui/src/main/resources/AppWithinMinutes/ClassEditSheet.xml+3 −3 modified@@ -104,7 +104,7 @@ xcontext.put('propertyCustomDisplayer', new PropertyCustomDisplayer(xcontext)) #foreach ($category in $services.query.xwql($categoryListStatement).execute()) #set ($categoryDoc = $xwiki.getDocument($category)) <li> - <div class="category">$categoryDoc.plainTitle</div> + <div class="category">$escapetool.xml($categoryDoc.plainTitle)</div> #set ($formFieldsForCategoryStatement = "from doc.object($formFieldClassName) as field where field.category = :category order by field.priority") #set ($formFieldsForCategoryQuery = $services.query.xwql($formFieldsForCategoryStatement).bindValue('category', $category)) <ul> @@ -119,7 +119,7 @@ xcontext.put('propertyCustomDisplayer', new PropertyCustomDisplayer(xcontext)) #else #set ($formFieldIconURL = $formFieldDoc.getAttachmentURL($formFieldIcon)) #end - #set ($formFieldIconRendered = "<img src='$formFieldIconURL' alt='$escapetool.xml($formFieldDoc.plainTitle)' class='icon' />") + #set ($formFieldIconRendered = "<img src='$escapetool.xml($formFieldIconURL)' alt='$escapetool.xml($formFieldDoc.plainTitle)' class='icon' />") #end <li class="field"> $formFieldIconRendered @@ -139,7 +139,7 @@ xcontext.put('propertyCustomDisplayer', new PropertyCustomDisplayer(xcontext)) 'field': $formFieldDoc.fullName, 'xeditmode': 'text' }))) - <input type="hidden" value="$fieldURL" class="data"/> + <input type="hidden" value="$escapetool.xml($fieldURL)" class="data"/> </li> #end </ul>
xwiki-platform-core/xwiki-platform-appwithinminutes/xwiki-platform-appwithinminutes-ui/src/test/java/org/xwikiplatform/appwithinminutes/ClassEditSheetPageTest.java+108 −0 added@@ -0,0 +1,108 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwikiplatform.appwithinminutes; + +import java.util.List; + +import org.jsoup.nodes.Document; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.xwiki.groovy.internal.DefaultGroovyConfiguration; +import org.xwiki.groovy.internal.GroovyScriptEngineFactory; +import org.xwiki.model.reference.DocumentReference; +import org.xwiki.query.Query; +import org.xwiki.query.script.QueryManagerScriptService; +import org.xwiki.rendering.internal.macro.groovy.GroovyMacro; +import org.xwiki.rendering.syntax.Syntax; +import org.xwiki.script.service.ScriptService; +import org.xwiki.test.annotation.ComponentList; +import org.xwiki.test.page.HTML50ComponentList; +import org.xwiki.test.page.PageTest; +import org.xwiki.test.page.XWikiSyntax21ComponentList; + +import com.xpn.xwiki.doc.XWikiDocument; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.when; + +/** + * Page Test of {@code AppWithinMinutes.ClassEditSheet}. + * + * @version $Id$ + * @since 14.4.8 + * @since 14.10.4 + * @since 15.0 + */ +@HTML50ComponentList +@XWikiSyntax21ComponentList +@ComponentList({ + // Start GroovyMacro + GroovyMacro.class, + GroovyScriptEngineFactory.class, + DefaultGroovyConfiguration.class + // End GroovyMacro +}) +class ClassEditSheetPageTest extends PageTest +{ + private QueryManagerScriptService queryManagerScriptService; + + @Mock + private Query query; + + @BeforeEach + void setUp() throws Exception + { + this.queryManagerScriptService = + this.componentManager.registerMockComponent(ScriptService.class, "query", QueryManagerScriptService.class, + false); + } + + @Test + void displayFieldPalette() throws Exception + { + loadPage(new DocumentReference("xwiki", "AppWithinMinutes", "VelocityMacros")); + loadPage(new DocumentReference("xwiki", "AppWithinMinutes", "ClassEditSheet")); + + when(this.queryManagerScriptService.xwql("from doc.object(AppWithinMinutes.FormFieldCategoryClass) as category " + + "order by category.priority")).thenReturn(this.query); + when(this.query.execute()).thenReturn(List.of("xwiki:XWiki.Category")); + + XWikiDocument xWikiDocumentCategory = + this.xwiki.getDocument(new DocumentReference("xwiki", "XWiki", "Category"), this.context); + xWikiDocumentCategory.setTitle("<strong>TITLE</strong>"); + this.xwiki.saveDocument(xWikiDocumentCategory, this.context); + + XWikiDocument xwikiDocument = + this.xwiki.getDocument(new DocumentReference("xwiki", "Space", "Page"), this.context); + + xwikiDocument.setContent("{{include reference=\"AppWithinMinutes.ClassEditSheet\" /}}\n" + + "\n" + + "{{velocity}}\n" + + "#displayFieldPalette()\n" + + "{{/velocity}}\n"); + xwikiDocument.setSyntax(Syntax.XWIKI_2_1); + this.xwiki.saveDocument(xwikiDocument, this.context); + + Document document = renderHTMLPage(xwikiDocument); + + assertEquals("<strong>TITLE</strong>", document.selectFirst(".category").text()); + } +}
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-4wc6-hqv9-qc97ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-35153ghsaADVISORY
- github.com/xwiki/xwiki-platform/commit/1b87fec1e5b5ec00b7a8c3c3f94f6c5e22547392ghsax_refsource_MISCWEB
- github.com/xwiki/xwiki-platform/security/advisories/GHSA-4wc6-hqv9-qc97ghsax_refsource_CONFIRMWEB
- jira.xwiki.org/browse/XWIKI-20365ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.