Improper Neutralization of Script-Related HTML Tags (XSS) in the LiveTable Macro
Description
XWiki Commons are technical libraries common to several other top level XWiki projects. The Livetable Macro wasn't properly sanitizing column names, thus allowing the insertion of raw HTML code including JavaScript. This vulnerability was also exploitable via the Documents Macro that is included since XWiki 3.5M1 and doesn't require script rights, this can be demonstrated with the syntax {{documents id="example" count="5" actions="false" columns="doc.title, before<script>alert(1)</script>after"/}}. Therefore, this can also be exploited by users without script right and in comments. With the interaction of a user with more rights, this could be used to execute arbitrary actions in the wiki, including privilege escalation, remote code execution, information disclosure, modifying or deleting content. This has been patched in XWiki 14.9, 14.4.6, and 13.10.10.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.xwiki.platform:xwiki-platform-flamingo-skin-resourcesMaven | >= 1.9-milestone-2, < 13.10.10 | 13.10.10 |
org.xwiki.platform:xwiki-platform-flamingo-skinMaven | >= 1.9-milestone-2, < 13.10.10 | 13.10.10 |
org.xwiki.platform:xwiki-platform-flamingoMaven | >= 1.9-milestone-2, < 13.10.10 | 13.10.10 |
org.xwiki.platform:xwiki-platform-web-templatesMaven | >= 1.9-milestone-2, < 13.10.10 | 13.10.10 |
org.xwiki.platform:xwiki-platform-webMaven | >= 1.9-milestone-2, < 13.10.10 | 13.10.10 |
org.xwiki.platform:xwiki-web-standardMaven | >= 1.9-milestone-2, < 13.10.10 | 13.10.10 |
org.xwiki.platform:xwiki-platform-flamingo-skin-resourcesMaven | >= 14.0-rc-1, < 14.4.6 | 14.4.6 |
org.xwiki.platform:xwiki-platform-flamingo-skinMaven | >= 14.0-rc-1, < 14.4.6 | 14.4.6 |
org.xwiki.platform:xwiki-platform-flamingoMaven | >= 14.0-rc-1, < 14.4.6 | 14.4.6 |
org.xwiki.platform:xwiki-platform-web-templatesMaven | >= 14.0-rc-1, < 14.4.6 | 14.4.6 |
org.xwiki.platform:xwiki-platform-webMaven | >= 14.0-rc-1, < 14.4.6 | 14.4.6 |
org.xwiki.platform:xwiki-web-standardMaven | >= 14.0-rc-1, < 14.4.6 | 14.4.6 |
org.xwiki.platform:xwiki-platform-flamingo-skin-resourcesMaven | >= 14.5, < 14.9 | 14.9 |
org.xwiki.platform:xwiki-platform-flamingo-skinMaven | >= 14.5, < 14.9 | 14.9 |
org.xwiki.platform:xwiki-platform-flamingoMaven | >= 14.5, < 14.9 | 14.9 |
org.xwiki.platform:xwiki-platform-web-templatesMaven | >= 14.5, < 14.9 | 14.9 |
org.xwiki.platform:xwiki-platform-webMaven | >= 14.5, < 14.9 | 14.9 |
org.xwiki.platform:xwiki-web-standardMaven | >= 14.5, < 14.9 | 14.9 |
Affected products
1- Range: >= 1.9-milestone-2, < 13.10.10
Patches
165ca06c51e7aXWIKI-15205: Improve escaping in LiveTable
2 files changed · +16 −16
xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/macros.vm+8 −8 modified@@ -233,12 +233,12 @@ #set($displayName = "#getLivetableColumnDisplayName($colname, $colprop, $transprefix)") #set ($defaultHeaderClass = {'_actions': 'actions', '_avatar': 'avatar'}) #set ($discard = $colprop.putIfAbsent('headerClass', $defaultHeaderClass.get($colname))) - <th scope="col" class="xwiki-livetable-display-header-text $!colprop.headerClass + <th scope="col" class="xwiki-livetable-display-header-text $!escapetool.xml($colprop.headerClass) #if ($!colprop.type == 'hidden')hidden#end #if ($isSortable)sortable #if ($colname == $selectedColumn)selected $defaultOrder#else asc#end#end"> #if($isFilterable)<label for="xwiki-livetable-${htmlLiveTableId}-filter-${foreach.count}">#end - #if($isSortable)<a data-rel="${colname}">#end - $displayName + #if($isSortable)<a data-rel="${escapetool.xml($colname)}">#end + $escapetool.xml($displayName) #if($isSortable)</a>#end #if($isFilterable)</label>#end #set($columnCount = $mathtool.add($columnCount, 1)) @@ -310,14 +310,14 @@ #end #end #if ($filterType == 'list' || $filterType == 'multilist') - <select id="xwiki-livetable-${htmlLiveTableId}-filter-${foreach.count}" name="$column" + <select id="xwiki-livetable-${htmlLiveTableId}-filter-${foreach.count}" name="$!escapetool.xml($column)" #if ($filterType == 'multilist') #set ($discard = $xwiki.jsfx.use('js/xwiki/table/livetablemulti.js', true)) #set ($discard = $xwiki.linkx.use($services.webjars.url('bootstrap-select', 'css/bootstrap-select.css'), {'type': 'text/css', 'rel': 'stylesheet'})) class="xwiki-livetable-multilist" multiple="multiple"> #else - ><option value="">$services.localization.render('platform.livetable.selectAll')</option> + ><option value="">$escapetool.xml($services.localization.render('platform.livetable.selectAll'))</option> <option disabled="disabled">────</option> #end #set ($storedValues = $xproperty.listValues) @@ -328,17 +328,17 @@ #if ($displayedValue == $l10nKey) #set ($displayedValue = $displayedValues.get($storedValue).value) #end - <option value="$storedValue">$displayedValue</option> + <option value="$!escapetool.xml($storedValue)">$!escapetool.xml($displayedValue)</option> #end </select> #elseif ($filterType == 'boolean') - <select id="xwiki-livetable-${htmlLiveTableId}-filter-${foreach.count}" name="$column"> + <select id="xwiki-livetable-${htmlLiveTableId}-filter-${foreach.count}" name="$!escapetool.xml($column)"> <option value="">$services.localization.render('platform.livetable.selectAll')</option> <option value="0">$services.localization.render('no')</option> <option value="1">$services.localization.render('yes')</option> </select> #elseif ($filterType == 'text' || $filterType == 'number') - <input id="xwiki-livetable-${htmlLiveTableId}-filter-${foreach.count}" name="$column" type="text" + <input id="xwiki-livetable-${htmlLiveTableId}-filter-${foreach.count}" name="$!escapetool.xml($column)" type="text" #if ("$!columnProperties.size" != '')size="$!escapetool.xml($columnProperties.size)"#end title="$escapetool.xml($services.localization.render('platform.livetable.filtersTitle', [$services.localization.render("${transprefix}$column")]))" />
xwiki-platform-core/xwiki-platform-web/xwiki-platform-web-templates/src/main/resources/templates/macros.vm+8 −8 modified@@ -1471,12 +1471,12 @@ $Msz MB## #set($displayName = "#getLivetableColumnDisplayName($colname, $colprop, $transprefix)") #set ($defaultHeaderClass = {'_actions': 'actions', '_avatar': 'avatar'}) #set ($discard = $colprop.putIfAbsent('headerClass', $defaultHeaderClass.get($colname))) - <th scope="col" class="xwiki-livetable-display-header-text $!colprop.headerClass + <th scope="col" class="xwiki-livetable-display-header-text $!escapetool.xml($colprop.headerClass) #if ($!colprop.type == 'hidden')hidden#end #if ($isSortable)sortable #if ($colname == $selectedColumn)selected $defaultOrder#else asc#end#end"> - #if($isSortable)<a rel="${colname}">#end + #if($isSortable)<a rel="${escapetool.xml($colname)}">#end #if($isFilterable)<label for="xwiki-livetable-${htmlLiveTableId}-filter-${foreach.count}">#end - $displayName + $escapetool.xml($displayName) #if($isFilterable)</label>#end #if($isSortable)</a>#end #set($columnCount = $mathtool.add($columnCount, 1)) @@ -1573,11 +1573,11 @@ $Msz MB## #set($escapedTitle = $escapetool.xml($services.localization.render('platform.livetable.filtersTitle', [$services.localization.render("${transprefix}$column")]))) #if ($filterType == 'list' || $filterType == 'multilist') - <select id="xwiki-livetable-${htmlLiveTableId}-filter-${foreach.count}" name="$column" + <select id="xwiki-livetable-${htmlLiveTableId}-filter-${foreach.count}" name="$!escapetool.xml($column)" #if ($filterType == 'multilist') class="xwiki-livetable-multilist" multiple="multiple"> #else - ><option value="">$services.localization.render('platform.livetable.selectAll')</option> + ><option value="">$escapetool.xml($services.localization.render('platform.livetable.selectAll'))</option> <option disabled="disabled">────</option> #end #set ($storedValues = $xproperty.listValues) @@ -1588,17 +1588,17 @@ $Msz MB## #if ($displayedValue == $l10nKey) #set ($displayedValue = $displayedValues.get($storedValue).value) #end - <option value="$storedValue">$displayedValue</option> + <option value="$!escapetool.xml($storedValue)">$!escapetool.xml($displayedValue)</option> #end </select> #elseif ($filterType == 'boolean') - <select id="xwiki-livetable-${htmlLiveTableId}-filter-${foreach.count}" name="$column"> + <select id="xwiki-livetable-${htmlLiveTableId}-filter-${foreach.count}" name="$!escapetool.xml($column)"> <option value="">$services.localization.render('platform.livetable.selectAll')</option> <option value="0">$services.localization.render('no')</option> <option value="1">$services.localization.render('yes')</option> </select> #elseif ($filterType == 'text' || $filterType == 'number') - <input id="xwiki-livetable-${htmlLiveTableId}-filter-${foreach.count}" name="$column" type="text" + <input id="xwiki-livetable-${htmlLiveTableId}-filter-${foreach.count}" name="$!escapetool.xml($column)" type="text" #if ("$!columnProperties.size" != '')size="$!escapetool.xml($columnProperties.size)"#end title="$escapedTitle"/> #elseif ($filterType == 'suggest' && $xproperty)
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-6vgh-9r3c-2cxpghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-29207ghsaADVISORY
- github.com/xwiki/xwiki-platform/commit/65ca06c51e7a1d5a579344c7272b2cc9a9a21126ghsax_refsource_MISCWEB
- github.com/xwiki/xwiki-platform/security/advisories/GHSA-6vgh-9r3c-2cxpghsax_refsource_CONFIRMWEB
- jira.xwiki.org/browse/XWIKI-15205ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.