XWiki uses the wrong wiki reference in AuthorizationManager
Description
XWiki Platform is a generic wiki platform. Prior to 15.10.14, 16.4.6, and 16.10.0-rc-1, it's possible for an user to get access to private information through the REST API - but could also be through another API - when a sub wiki is using "Prevent unregistered users to view pages". The vulnerability only affects subwikis, and it only concerns specific right options such as "Prevent unregistered users to view pages". or "Prevent unregistered users to edit pages". It's possible to detect the vulnerability by enabling "Prevent unregistered users to view pages" and then trying to access a page through the REST API without using any credentials. The vulnerability has been patched in XWiki 15.10.14, 16.4.6 and 16.10.0RC1.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.xwiki.platform:xwiki-platform-security-authorization-apiMaven | >= 6.1-rc-1, < 15.10.14 | 15.10.14 |
org.xwiki.platform:xwiki-platform-security-authorization-apiMaven | >= 16.0.0-rc-1, < 16.4.6 | 16.4.6 |
org.xwiki.platform:xwiki-platform-security-authorization-apiMaven | >= 16.5.0-rc-1, < 16.10.0-rc-1 | 16.10.0-rc-1 |
Affected products
1- Range: >= 6.1-rc-1, < 15.10.14
Patches
15f98bde87288XWIKI-22640: DefaultAuthorizationManager doesn't properly set the wiki reference
2 files changed · +46 −10
xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/main/java/org/xwiki/security/authorization/DefaultAuthorizationManager.java+25 −10 modified@@ -30,6 +30,7 @@ import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.xwiki.component.annotation.Component; +import org.xwiki.model.ModelContext; import org.xwiki.model.reference.DocumentReference; import org.xwiki.model.reference.EntityReference; import org.xwiki.model.reference.EntityReferenceSerializer; @@ -49,6 +50,8 @@ */ @Component @Singleton +// The fan-out is of 21 instead of 20 after introducing the ModelContext, not an easy one to refactor. +@SuppressWarnings("checkstyle:ClassFanOutComplexity") public class DefaultAuthorizationManager implements AuthorizationManager { /** @@ -83,6 +86,9 @@ public class DefaultAuthorizationManager implements AuthorizationManager @Inject private DocumentRequiredRightsChecker documentRequiredRightsChecker; + @Inject + private ModelContext modelContext; + /** * Check if the user is the super admin. * @@ -156,21 +162,30 @@ private boolean hasSecurityAccess(Right right, DocumentReference userReference, return false; } - if ((!right.isReadOnly() && xwikiBridge.isWikiReadOnly()) - || (userReference == null && xwikiBridge.needsAuthentication(right))) { + if (checkWikiPreferencesDiscardAccess(right, userReference, entityReference)) { return false; } - // For edit right, check if the user has all required rights. - if (right == Right.EDIT && !this.documentRequiredRightsChecker.hasRequiredRights(userReference, - entityReference)) - { - logDenyIfCheck(right, userReference, entityReference, check, "misses required right"); + return evaluateSecurityAccess(right, userReference, entityReference, check); + } - return false; + private boolean checkWikiPreferencesDiscardAccess(Right right, DocumentReference userReference, + EntityReference entityReference) + { + if (entityReference != null) { + EntityReference currentEntityReference = this.modelContext.getCurrentEntityReference(); + this.modelContext.setCurrentEntityReference(entityReference); + + try { + if ((!right.isReadOnly() && xwikiBridge.isWikiReadOnly()) + || (userReference == null && xwikiBridge.needsAuthentication(right))) { + return true; + } + } finally { + this.modelContext.setCurrentEntityReference(currentEntityReference); + } } - - return evaluateSecurityAccess(right, userReference, entityReference, check); + return false; } private void logDenyIfCheck(Right right, DocumentReference userReference, EntityReference entityReference,
xwiki-platform-core/xwiki-platform-security/xwiki-platform-security-authorization/xwiki-platform-security-authorization-api/src/test/java/org/xwiki/security/authorization/DefaultAuthorizationManagerIntegrationTest.java+21 −0 modified@@ -36,6 +36,7 @@ import org.xwiki.cache.CacheManager; import org.xwiki.cache.config.CacheConfiguration; import org.xwiki.model.EntityType; +import org.xwiki.model.ModelContext; import org.xwiki.model.internal.DefaultModelConfiguration; import org.xwiki.model.internal.reference.DefaultEntityReferenceProvider; import org.xwiki.model.internal.reference.DefaultStringEntityReferenceResolver; @@ -93,6 +94,7 @@ import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.xwiki.security.authorization.Right.ADMIN; import static org.xwiki.security.authorization.Right.COMMENT; @@ -135,6 +137,9 @@ class DefaultAuthorizationManagerIntegrationTest extends AbstractAuthorizationTe @MockComponent private UserBridge userBridge; + @MockComponent + private ModelContext modelContext; + /** Mocked securityEntryReader */ @MockComponent private SecurityEntryReader securityEntryReader; @@ -152,6 +157,8 @@ class DefaultAuthorizationManagerIntegrationTest extends AbstractAuthorizationTe /** Factory for security reference */ private SecurityReferenceFactory securityReferenceFactory; + private DocumentReference currentEntityReference = new DocumentReference("xwiki", "Page", "Space"); + @BeforeComponent void initializeMocks() throws Exception { @@ -177,6 +184,7 @@ void setUp() throws Exception { securityReferenceFactory = componentManager.getInstance(SecurityReferenceFactory.class); authorizationManager = componentManager.getInstance(AuthorizationManager.class); + when(this.modelContext.getCurrentEntityReference()).thenReturn(currentEntityReference); } /** @@ -466,7 +474,20 @@ void defaultAccessOnEmptyWikis() throws Exception // Any Local user on another subwiki assertAccess(null, getUser("a local user", "any SubWiki"), getDoc("an another subwiki", "anySpace", "any Other SubWiki")); + } + @Test + void verifyNeedsAuthentication() throws Exception + { + initialiseWikiMock("emptyWikis"); + when(this.xWikiBridge.needsAuthentication(VIEW)).thenReturn(true); + DocumentReference documentReference = getXDoc("an empty main wiki", "anySpace"); + assertFalse(authorizationManager.hasAccess(VIEW, null, documentReference)); + verify(this.modelContext).setCurrentEntityReference(documentReference); + verify(this.modelContext).setCurrentEntityReference(currentEntityReference); + + when(this.xWikiBridge.needsAuthentication(VIEW)).thenReturn(false); + assertTrue(authorizationManager.hasAccess(VIEW, null, documentReference)); } @Test
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-gq32-758c-3wm3ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-29924ghsaADVISORY
- github.com/xwiki/xwiki-platform/commit/5f98bde87288326cf5787604e2bb87836875ed0eghsax_refsource_MISCWEB
- github.com/xwiki/xwiki-platform/security/advisories/GHSA-gq32-758c-3wm3ghsax_refsource_CONFIRMWEB
- jira.xwiki.org/browse/XWIKI-22640ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.