XWiki Platform XSS through conflict resolution
Description
XWiki Platform is a generic wiki platform offering runtime services for applications built on top of it. By creating a conflict when another user with more rights is currently editing a page, it is possible to execute JavaScript snippets on the side of the other user, which compromises the confidentiality, integrity and availability of the whole XWiki installation. This has been patched in XWiki 15.10.8 and 16.3.0RC1.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.xwiki.platform:xwiki-platform-web-templatesMaven | >= 11.8-rc-1, < 15.10.8 | 15.10.8 |
org.xwiki.platform:xwiki-platform-web-templatesMaven | >= 16.0.0-rc-1, < 16.3.0-rc-1 | 16.3.0-rc-1 |
Affected products
1- Range: >= 11.8-rc-1, < 15.10.8
Patches
2821d43ec45e6XWIKI-21626: Improve escaping during conflict resolution
2 files changed · +16 −7
xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/EditIT.java+6 −6 modified@@ -677,7 +677,7 @@ public void editWithConflict(TestUtils setup, TestReference testReference) wikiEditPageTab1.setContent( "First line." - + "\nSecond line." + + "\n<script>alert('Second line.')</script>" + "\nLine N°4" + "\nFifth line." + "\n6th line." @@ -690,9 +690,9 @@ public void editWithConflict(TestUtils setup, TestReference testReference) assertEquals(EditConflictModal.ConflictChoice.MERGE, editConflictModal.getCurrentChoice()); assertEquals(Arrays.asList("@@ -1,6 +1,6 @@", " First line.", - "-<del>L</del>ine<del> N°2</del>", + "-<del>L</del>i<del>n</del>e <del>N°2</del>", "-<del>Th</del>i<del>rd li</del>ne<del>.</del>", - "+<ins>Second l</ins>ine<ins>.</ins>", + "+<ins><scr</ins>i<ins>pt>al</ins>e<ins>rt('Second</ins> <ins>line.')</script></ins>", "+<ins>L</ins>ine<ins> N°4</ins>", " Fifth line.", "-<del>Six</del>th line.", @@ -705,9 +705,9 @@ public void editWithConflict(TestUtils setup, TestReference testReference) assertEquals(Arrays.asList("@@ -1,1 +1,1 @@", " First line.", "@@ -2,2 +2,2 @@", - "-<del>L</del>ine<del> N°2</del>", + "-<del>L</del>i<del>n</del>e <del>N°2</del>", "-<del>Th</del>i<del>rd li</del>ne<del>.</del>", - "+<ins>Second l</ins>ine<ins>.</ins>", + "+<ins><scr</ins>i<ins>pt>al</ins>e<ins>rt('Second</ins> <ins>line.')</script></ins>", "+<ins>L</ins>ine<ins> N°4</ins>", "[Conflict Resolution]", "@@ -4,1 +4,1 @@", @@ -727,7 +727,7 @@ public void editWithConflict(TestUtils setup, TestReference testReference) assertEquals(Conflict.DecisionType.CURRENT, conflict.getCurrentDecision()); assertFalse(conflict.isDecisionChangeEmpty()); - assertEquals("Second line.\nLine N°4", conflict.getDecisionChange()); + assertEquals("<script>alert('Second line.')</script>\nLine N°4", conflict.getDecisionChange()); conflict.setDecision(Conflict.DecisionType.PREVIOUS); assertFalse(conflict.isDecisionChangeEmpty()); assertEquals("Second line.\nThird line.", conflict.getDecisionChange());
xwiki-platform-core/xwiki-platform-web/xwiki-platform-web-templates/src/main/resources/templates/diff_macros.vm+10 −1 modified@@ -82,7 +82,16 @@ #else #set ($spanClass = "diff-decision") #end - <span class="$spanClass" id="$spanId">$stringtool.join($value, "<br/>")</span> + +## We do not want the renderer to add any extra spaces or linebreaks in this output. +#* *#<span class="$spanClass" id="$spanId">## +#* *##foreach ($v in $value) +#* *#$escapetool.xml($v)## +#* *##if ($foreach.hasNext) +#* *#<br/>## +#* *##end +#* *##end +#* *#</span> #end #macro (displayPropertyDiff $propertyName $previousValue $newValue $_obfuscate $conflicts $realPropertyName)
e00e159d3737XWIKI-21626: Improve escaping during conflict resolution
2 files changed · +16 −7
xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/EditIT.java+6 −6 modified@@ -677,7 +677,7 @@ public void editWithConflict(TestUtils setup, TestReference testReference) wikiEditPageTab1.setContent( "First line." - + "\nSecond line." + + "\n<script>alert('Second line.')</script>" + "\nLine N°4" + "\nFifth line." + "\n6th line." @@ -690,9 +690,9 @@ public void editWithConflict(TestUtils setup, TestReference testReference) assertEquals(EditConflictModal.ConflictChoice.MERGE, editConflictModal.getCurrentChoice()); assertEquals(Arrays.asList("@@ -1,6 +1,6 @@", " First line.", - "-<del>L</del>ine<del> N°2</del>", + "-<del>L</del>i<del>n</del>e <del>N°2</del>", "-<del>Th</del>i<del>rd li</del>ne<del>.</del>", - "+<ins>Second l</ins>ine<ins>.</ins>", + "+<ins><scr</ins>i<ins>pt>al</ins>e<ins>rt('Second</ins> <ins>line.')</script></ins>", "+<ins>L</ins>ine<ins> N°4</ins>", " Fifth line.", "-<del>Six</del>th line.", @@ -705,9 +705,9 @@ public void editWithConflict(TestUtils setup, TestReference testReference) assertEquals(Arrays.asList("@@ -1,1 +1,1 @@", " First line.", "@@ -2,2 +2,2 @@", - "-<del>L</del>ine<del> N°2</del>", + "-<del>L</del>i<del>n</del>e <del>N°2</del>", "-<del>Th</del>i<del>rd li</del>ne<del>.</del>", - "+<ins>Second l</ins>ine<ins>.</ins>", + "+<ins><scr</ins>i<ins>pt>al</ins>e<ins>rt('Second</ins> <ins>line.')</script></ins>", "+<ins>L</ins>ine<ins> N°4</ins>", "[Conflict Resolution]", "@@ -4,1 +4,1 @@", @@ -727,7 +727,7 @@ public void editWithConflict(TestUtils setup, TestReference testReference) assertEquals(Conflict.DecisionType.CURRENT, conflict.getCurrentDecision()); assertFalse(conflict.isDecisionChangeEmpty()); - assertEquals("Second line.\nLine N°4", conflict.getDecisionChange()); + assertEquals("<script>alert('Second line.')</script>\nLine N°4", conflict.getDecisionChange()); conflict.setDecision(Conflict.DecisionType.PREVIOUS); assertFalse(conflict.isDecisionChangeEmpty()); assertEquals("Second line.\nThird line.", conflict.getDecisionChange());
xwiki-platform-core/xwiki-platform-web/xwiki-platform-web-templates/src/main/resources/templates/diff_macros.vm+10 −1 modified@@ -82,7 +82,16 @@ #else #set ($spanClass = "diff-decision") #end - <span class="$spanClass" id="$spanId">$stringtool.join($value, "<br/>")</span> + +## We do not want the renderer to add any extra spaces or linebreaks in this output. +#* *#<span class="$spanClass" id="$spanId">## +#* *##foreach ($v in $value) +#* *#$escapetool.xml($v)## +#* *##if ($foreach.hasNext) +#* *#<br/>## +#* *##end +#* *##end +#* *#</span> #end #macro (displayPropertyDiff $propertyName $previousValue $newValue $_obfuscate $conflicts $realPropertyName)
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
6- github.com/advisories/GHSA-692v-783f-mg8xghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-41947ghsaADVISORY
- github.com/xwiki/xwiki-platform/commit/821d43ec45e67d45a6735a0717b9b77fffc1cd9fghsax_refsource_MISCWEB
- github.com/xwiki/xwiki-platform/commit/e00e159d3737397eebd1f6ff925c1f5cb7cdec34ghsax_refsource_MISCWEB
- github.com/xwiki/xwiki-platform/security/advisories/GHSA-692v-783f-mg8xghsax_refsource_CONFIRMWEB
- jira.xwiki.org/browse/XWIKI-21626ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.