VYPR
High severityNVD Advisory· Published Apr 15, 2023· Updated Feb 6, 2025

Improper Neutralization of Script-Related HTML Tags (XSS) in the LiveTable Macro

CVE-2023-29207

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.

PackageAffected versionsPatched versions
org.xwiki.platform:xwiki-platform-flamingo-skin-resourcesMaven
>= 1.9-milestone-2, < 13.10.1013.10.10
org.xwiki.platform:xwiki-platform-flamingo-skinMaven
>= 1.9-milestone-2, < 13.10.1013.10.10
org.xwiki.platform:xwiki-platform-flamingoMaven
>= 1.9-milestone-2, < 13.10.1013.10.10
org.xwiki.platform:xwiki-platform-web-templatesMaven
>= 1.9-milestone-2, < 13.10.1013.10.10
org.xwiki.platform:xwiki-platform-webMaven
>= 1.9-milestone-2, < 13.10.1013.10.10
org.xwiki.platform:xwiki-web-standardMaven
>= 1.9-milestone-2, < 13.10.1013.10.10
org.xwiki.platform:xwiki-platform-flamingo-skin-resourcesMaven
>= 14.0-rc-1, < 14.4.614.4.6
org.xwiki.platform:xwiki-platform-flamingo-skinMaven
>= 14.0-rc-1, < 14.4.614.4.6
org.xwiki.platform:xwiki-platform-flamingoMaven
>= 14.0-rc-1, < 14.4.614.4.6
org.xwiki.platform:xwiki-platform-web-templatesMaven
>= 14.0-rc-1, < 14.4.614.4.6
org.xwiki.platform:xwiki-platform-webMaven
>= 14.0-rc-1, < 14.4.614.4.6
org.xwiki.platform:xwiki-web-standardMaven
>= 14.0-rc-1, < 14.4.614.4.6
org.xwiki.platform:xwiki-platform-flamingo-skin-resourcesMaven
>= 14.5, < 14.914.9
org.xwiki.platform:xwiki-platform-flamingo-skinMaven
>= 14.5, < 14.914.9
org.xwiki.platform:xwiki-platform-flamingoMaven
>= 14.5, < 14.914.9
org.xwiki.platform:xwiki-platform-web-templatesMaven
>= 14.5, < 14.914.9
org.xwiki.platform:xwiki-platform-webMaven
>= 14.5, < 14.914.9
org.xwiki.platform:xwiki-web-standardMaven
>= 14.5, < 14.914.9

Affected products

1

Patches

1
65ca06c51e7a

XWIKI-15205: Improve escaping in LiveTable

https://github.com/xwiki/xwiki-platformMichael HamannOct 18, 2022via ghsa
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

News mentions

0

No linked articles in our index yet.