XWiki does not require right warnings for notification displayer objects
Description
XWiki is an open-source wiki software platform. When a user without script right creates a document with an XWiki.Notifications.Code.NotificationDisplayerClass object, and later an admin edits and saves that document, the possibly malicious content of that object is output as raw HTML, allowing XSS attacks. While the notification displayer executes Velocity, the existing generic analyzer already warns admins before editing Velocity code. Note that warnings before editing documents with dangerous properties have only been introduced in XWiki 15.9, before that version, this was a known issue and the advice was simply to be careful. This vulnerability has been patched in XWiki 15.10.16, 16.4.7, and 16.10.2 by adding a required rights analyzer that warns the admin before editing about the possibly malicious code.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.xwiki.platform:xwiki-platform-notifications-notifiers-defaultMaven | >= 15.9-rc-1, < 15.10.16 | 15.10.16 |
org.xwiki.platform:xwiki-platform-notifications-notifiers-defaultMaven | >= 16.0.0-rc-1, < 16.4.7 | 16.4.7 |
org.xwiki.platform:xwiki-platform-notifications-notifiers-defaultMaven | >= 16.5.0-rc-1, < 16.10.2 | 16.10.2 |
Affected products
1- Range: >= 15.9-rc-1, < 15.10.16
Patches
155c5d568c4dcXWIKI-22470: Add a required rights analyzer for XWiki.Notifications.Code.NotificationDisplayerClass
4 files changed · +221 −0
xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-notifiers/xwiki-platform-notifications-notifiers-default/src/main/java/org/xwiki/notifications/notifiers/internal/WikiNotificationDisplayerRequiredRightAnalyzer.java+83 −0 added@@ -0,0 +1,83 @@ +/* + * 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.xwiki.notifications.notifiers.internal; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; +import org.xwiki.platform.security.requiredrights.RequiredRight; +import org.xwiki.platform.security.requiredrights.RequiredRightAnalysisResult; +import org.xwiki.platform.security.requiredrights.RequiredRightAnalyzer; +import org.xwiki.platform.security.requiredrights.display.BlockSupplierProvider; +import org.xwiki.velocity.internal.util.VelocityDetector; + +import com.xpn.xwiki.objects.BaseObject; + +/** + * {@link RequiredRightAnalyzer} for wiki notification displayers. + * + * @version $Id$ + */ +@Component +@Named(WikiNotificationDisplayerDocumentInitializer.XCLASS_NAME) +@Singleton +public class WikiNotificationDisplayerRequiredRightAnalyzer implements RequiredRightAnalyzer<BaseObject> +{ + @Inject + @Named("translation") + private BlockSupplierProvider<String> translationMessageSupplierProvider; + + @Inject + private BlockSupplierProvider<BaseObject> baseObjectBlockSupplierProvider; + + @Inject + private VelocityDetector velocityDetector; + + @Override + public List<RequiredRightAnalysisResult> analyze(BaseObject object) + { + List<RequiredRightAnalysisResult> result = new ArrayList<>(); + + if (object != null) { + String template = + object.getStringValue(WikiNotificationDisplayerDocumentInitializer.NOTIFICATION_TEMPLATE); + if (this.velocityDetector.containsVelocityScript(template)) { + result.add(new RequiredRightAnalysisResult(object.getReference(), + this.translationMessageSupplierProvider.get( + "notifications.notifiers.wikiNotificationDisplayerRequiredRightWithScript"), + this.baseObjectBlockSupplierProvider.get(object), + List.of(RequiredRight.WIKI_ADMIN, RequiredRight.MAYBE_PROGRAM))); + } else { + result.add(new RequiredRightAnalysisResult(object.getReference(), + this.translationMessageSupplierProvider.get( + "notifications.notifiers.wikiNotificationDisplayerRequiredRight"), + this.baseObjectBlockSupplierProvider.get(object), + List.of(RequiredRight.WIKI_ADMIN))); + } + } + + return result; + } +}
xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-notifiers/xwiki-platform-notifications-notifiers-default/src/main/resources/ApplicationResources.properties+4 −0 modified@@ -43,3 +43,7 @@ ############################################################################### notification.error.failedRender=Error while rendering notification +notifications.notifiers.wikiNotificationDisplayerRequiredRight=Wiki notification displayer objects require wiki \ + administration rights. +notifications.notifiers.wikiNotificationDisplayerRequiredRightWithScript=Wiki notification displayer objects require \ + wiki administration rights, the Velocity code in the template script might additionally require programming right.
xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-notifiers/xwiki-platform-notifications-notifiers-default/src/main/resources/META-INF/components.txt+1 −0 modified@@ -6,6 +6,7 @@ org.xwiki.notifications.notifiers.internal.UserEventManager org.xwiki.notifications.notifiers.internal.WikiNotificationDisplayer org.xwiki.notifications.notifiers.internal.WikiNotificationDisplayerComponentBuilder org.xwiki.notifications.notifiers.internal.WikiNotificationDisplayerDocumentInitializer +org.xwiki.notifications.notifiers.internal.WikiNotificationDisplayerRequiredRightAnalyzer org.xwiki.notifications.notifiers.internal.email.DefaultNotificationEmailRenderer org.xwiki.notifications.notifiers.internal.email.DefaultPeriodicMimeMessageIterator org.xwiki.notifications.notifiers.internal.email.DefaultEmailTemplateRenderer
xwiki-platform-core/xwiki-platform-notifications/xwiki-platform-notifications-notifiers/xwiki-platform-notifications-notifiers-default/src/test/java/org/xwiki/notifications/notifiers/internal/WikiNotificationDisplayerRequiredRightAnalyzerTest.java+133 −0 added@@ -0,0 +1,133 @@ +/* + * 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.xwiki.notifications.notifiers.internal; + +import java.util.List; +import java.util.function.Supplier; + +import javax.inject.Named; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.xwiki.platform.security.requiredrights.RequiredRight; +import org.xwiki.platform.security.requiredrights.RequiredRightAnalysisResult; +import org.xwiki.platform.security.requiredrights.display.BlockSupplierProvider; +import org.xwiki.rendering.block.Block; +import org.xwiki.rendering.block.WordBlock; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; +import org.xwiki.velocity.internal.util.VelocityDetector; + +import com.xpn.xwiki.objects.BaseObject; +import com.xpn.xwiki.objects.BaseObjectReference; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Component test for {@link WikiNotificationDisplayerRequiredRightAnalyzer}. + * + * @version $Id$ + */ +@ComponentTest +class WikiNotificationDisplayerRequiredRightAnalyzerTest +{ + protected static final String PRETTY_NAME = "Pretty Name"; + + protected static final BaseObjectReference OBJECT_REFERENCE = mock(); + + @InjectMockComponents + private WikiNotificationDisplayerRequiredRightAnalyzer analyzer; + + @MockComponent + @Named("translation") + private BlockSupplierProvider<String> translationMessageSupplierProvider; + + @MockComponent + private BlockSupplierProvider<BaseObject> baseObjectBlockSupplierProvider; + + @MockComponent + private VelocityDetector velocityDetector; + + @Mock + private BaseObject baseObject; + + @BeforeEach + void setup() + { + when(this.translationMessageSupplierProvider.get(anyString())).then(invocation -> { + String message = invocation.getArgument(0); + return (Supplier<Block>) () -> new WordBlock(message); + }); + when(this.baseObjectBlockSupplierProvider.get(this.baseObject)).then(invocation -> { + BaseObject object = invocation.getArgument(0); + return (Supplier<Block>) () -> new WordBlock(object.getPrettyName()); + }); + + when(this.baseObject.getReference()).thenReturn(OBJECT_REFERENCE); + when(this.baseObject.getPrettyName()).thenReturn(PRETTY_NAME); + } + + @Test + void analyzeWithoutScript() + { + List<RequiredRightAnalysisResult> results = this.analyzer.analyze(this.baseObject); + + assertEquals(1, results.size()); + RequiredRightAnalysisResult result = results.get(0); + assertEquals(OBJECT_REFERENCE, result.getEntityReference()); + assertEquals(new WordBlock("notifications.notifiers.wikiNotificationDisplayerRequiredRight"), + result.getSummaryMessage()); + assertEquals(new WordBlock(PRETTY_NAME), result.getDetailedMessage()); + assertEquals(List.of(RequiredRight.WIKI_ADMIN), result.getRequiredRights()); + } + + @Test + void analyzeWithScript() + { + String template = "template"; + when(this.baseObject.getStringValue(WikiNotificationDisplayerDocumentInitializer.NOTIFICATION_TEMPLATE)) + .thenReturn(template); + when(this.velocityDetector.containsVelocityScript(template)).thenReturn(true); + + List<RequiredRightAnalysisResult> results = this.analyzer.analyze(this.baseObject); + + assertEquals(1, results.size()); + RequiredRightAnalysisResult result = results.get(0); + assertEquals(OBJECT_REFERENCE, result.getEntityReference()); + assertEquals(new WordBlock("notifications.notifiers.wikiNotificationDisplayerRequiredRightWithScript"), + result.getSummaryMessage()); + assertEquals(new WordBlock(PRETTY_NAME), result.getDetailedMessage()); + assertEquals(List.of(RequiredRight.WIKI_ADMIN, RequiredRight.MAYBE_PROGRAM), result.getRequiredRights()); + } + + @Test + void analyzeWithNullBaseObject() + { + List<RequiredRightAnalysisResult> results = this.analyzer.analyze(null); + + assertTrue(results.isEmpty()); + } +}
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-j7p2-87q3-44w7ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-49587ghsaADVISORY
- github.com/xwiki/xwiki-platform/commit/55c5d568c4dc4619f37397d00d14dcdeab9c252dghsax_refsource_MISCWEB
- github.com/xwiki/xwiki-platform/security/advisories/GHSA-j7p2-87q3-44w7ghsax_refsource_CONFIRMWEB
- jira.xwiki.org/browse/XWIKI-22470ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.