The lesscss script service allows cache clearing without programming right
Description
XWiki is a generic wiki platform. In versions starting from 6.1-milestone-1 to before 15.10.12, from 16.0.0-rc-1 to before 16.4.3, and from 16.5.0-rc-1 to before 16.8.0-rc-1, the script API of the LESS compiler in XWiki is incorrectly checking for rights when calling the cache cleaning API, making it possible to clean the cache without having programming right. The only impact of this is a slowdown in XWiki execution as the caches are re-filled. As this vulnerability requires script right to exploit, and script right already allows unlimited execution of scripts, the additional impact due to this vulnerability is low. This issue has been patched in versions 15.10.12, 16.4.3, and 16.8.0-rc-1.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.xwiki.platform:xwiki-platform-lesscss-scriptMaven | >= 6.1-milestone-1, < 15.10.12 | 15.10.12 |
org.xwiki.platform:xwiki-platform-lesscss-scriptMaven | >= 16.0.0-rc-1, < 16.4.3 | 16.4.3 |
org.xwiki.platform:xwiki-platform-lesscss-scriptMaven | >= 16.5.0-rc-1, < 16.8.0-rc-1 | 16.8.0-rc-1 |
Affected products
1- Range: >= 6.1-milestone-1, < 15.10.12
Patches
191752122d878XWIKI-22462: Use the contextual authorization manager in the lesscss script service
2 files changed · +41 −29
xwiki-platform-core/xwiki-platform-lesscss/xwiki-platform-lesscss-script/src/main/java/org/xwiki/lesscss/LessCompilerScriptService.java+5 −20 modified@@ -21,7 +21,6 @@ import javax.inject.Inject; import javax.inject.Named; -import javax.inject.Provider; import javax.inject.Singleton; import org.apache.commons.lang3.exception.ExceptionUtils; @@ -38,11 +37,9 @@ import org.xwiki.lesscss.internal.skin.SkinReferenceFactory; import org.xwiki.lesscss.resources.LESSResourceReferenceFactory; import org.xwiki.script.service.ScriptService; -import org.xwiki.security.authorization.AuthorizationManager; +import org.xwiki.security.authorization.ContextualAuthorizationManager; import org.xwiki.security.authorization.Right; -import com.xpn.xwiki.XWikiContext; - /** * This script service provides a LESS preprocessor (http://lesscss.org/) for CSS generation. * @@ -66,9 +63,6 @@ public class LessCompilerScriptService implements ScriptService @Inject private ColorThemeCache colorThemeCache; - @Inject - private Provider<XWikiContext> xcontextProvider; - @Inject private LESSColorThemeConverter lessColorThemeConverter; @@ -79,7 +73,7 @@ public class LessCompilerScriptService implements ScriptService private ColorThemeReferenceFactory colorThemeReferenceFactory; @Inject - private AuthorizationManager authorizationManager; + private ContextualAuthorizationManager authorizationManager; /** * Compile a LESS file located in the "less" directory of the current skin directory. @@ -184,11 +178,8 @@ public ColorTheme getColorThemeFromSkinFile(String filename, String skin) */ public boolean clearCache() { - XWikiContext xcontext = xcontextProvider.get(); - // Check if the current script has the programing rights - if (!authorizationManager.hasAccess(Right.PROGRAM, xcontext.getDoc().getAuthorReference(), - xcontext.getDoc().getDocumentReference())) { + if (!authorizationManager.hasAccess(Right.PROGRAM)) { return false; } @@ -205,11 +196,8 @@ public boolean clearCache() */ public boolean clearCacheFromColorTheme(String colorTheme) { - XWikiContext xcontext = xcontextProvider.get(); - // Check if the current script has the programing rights - if (!authorizationManager.hasAccess(Right.PROGRAM, xcontext.getDoc().getAuthorReference(), - xcontext.getDoc().getDocumentReference())) { + if (!authorizationManager.hasAccess(Right.PROGRAM)) { return false; } @@ -233,11 +221,8 @@ public boolean clearCacheFromColorTheme(String colorTheme) */ public boolean clearCacheFromSkin(String skin) { - XWikiContext xcontext = xcontextProvider.get(); - // Check if the current script has the programing rights - if (!authorizationManager.hasAccess(Right.PROGRAM, xcontext.getDoc().getAuthorReference(), - xcontext.getDoc().getDocumentReference())) { + if (!authorizationManager.hasAccess(Right.PROGRAM)) { return false; }
xwiki-platform-core/xwiki-platform-lesscss/xwiki-platform-lesscss-script/src/test/java/org/xwiki/lesscss/LessCompilerScriptServiceTest.java+36 −9 modified@@ -37,7 +37,7 @@ import org.xwiki.lesscss.resources.LESSResourceReference; import org.xwiki.lesscss.resources.LESSResourceReferenceFactory; import org.xwiki.model.reference.DocumentReference; -import org.xwiki.security.authorization.AuthorizationManager; +import org.xwiki.security.authorization.ContextualAuthorizationManager; import org.xwiki.security.authorization.Right; import org.xwiki.test.mockito.MockitoComponentMockingRule; @@ -74,7 +74,7 @@ public class LessCompilerScriptServiceTest private LESSColorThemeConverter lessColorThemeConverter; - private AuthorizationManager authorizationManager; + private ContextualAuthorizationManager authorizationManager; private Provider<XWikiContext> xcontextProvider; @@ -92,7 +92,7 @@ public void setUp() throws Exception lessCache = mocker.getInstance(LESSResourcesCache.class); lessResourceReferenceFactory = mocker.getInstance(LESSResourceReferenceFactory.class); colorThemeCache = mocker.getInstance(ColorThemeCache.class); - authorizationManager = mocker.getInstance(AuthorizationManager.class); + authorizationManager = mocker.getInstance(ContextualAuthorizationManager.class); skinReferenceFactory = mocker.getInstance(SkinReferenceFactory.class); colorThemeReferenceFactory = mocker.getInstance(ColorThemeReferenceFactory.class); xcontextProvider = mocker.registerMockComponent(XWikiContext.TYPE_PROVIDER); @@ -247,7 +247,7 @@ public void clearCacheWithRights() throws Exception DocumentReference currentDocReference = new DocumentReference("wiki", "Space", "Page"); when(doc.getDocumentReference()).thenReturn(currentDocReference); - when(authorizationManager.hasAccess(Right.PROGRAM, authorReference, currentDocReference)).thenReturn(true); + when(authorizationManager.hasAccess(Right.PROGRAM)).thenReturn(true); // Tests assertTrue(mocker.getComponentUnderTest().clearCache()); @@ -268,7 +268,7 @@ public void clearCacheWithoutRights() throws Exception DocumentReference currentDocReference = new DocumentReference("wiki", "Space", "Page"); when(doc.getDocumentReference()).thenReturn(currentDocReference); - when(authorizationManager.hasAccess(Right.PROGRAM, authorReference, currentDocReference)).thenReturn(false); + when(authorizationManager.hasAccess(Right.PROGRAM)).thenReturn(false); // Tests assertFalse(mocker.getComponentUnderTest().clearCache()); @@ -289,7 +289,7 @@ public void clearCacheFromColorThemeWithRights() throws Exception DocumentReference currentDocReference = new DocumentReference("wiki", "Space", "Page"); when(doc.getDocumentReference()).thenReturn(currentDocReference); - when(authorizationManager.hasAccess(Right.PROGRAM, authorReference, currentDocReference)).thenReturn(true); + when(authorizationManager.hasAccess(Right.PROGRAM)).thenReturn(true); ColorThemeReference colorThemeReference = mock(ColorThemeReference.class); when(colorThemeReferenceFactory.createReference("colorTheme")).thenReturn(colorThemeReference); @@ -313,7 +313,7 @@ public void clearCacheFromColorThemeWithoutRights() throws Exception DocumentReference currentDocReference = new DocumentReference("wiki", "Space", "Page"); when(doc.getDocumentReference()).thenReturn(currentDocReference); - when(authorizationManager.hasAccess(Right.PROGRAM, authorReference, currentDocReference)).thenReturn(false); + when(authorizationManager.hasAccess(Right.PROGRAM)).thenReturn(false); // Tests assertFalse(mocker.getComponentUnderTest().clearCacheFromColorTheme("colorTheme")); @@ -323,6 +323,20 @@ public void clearCacheFromColorThemeWithoutRights() throws Exception verifyNoInteractions(colorThemeCache); } + @Test + public void clearCacheFromColorThemeWithException() throws Exception + { + when(this.authorizationManager.hasAccess(Right.PROGRAM)).thenReturn(true); + + LESSCompilerException lessCompilerException = new LESSCompilerException("Test Exception"); + when(this.colorThemeReferenceFactory.createReference("colorTheme")).thenThrow(lessCompilerException); + + assertFalse(mocker.getComponentUnderTest().clearCacheFromColorTheme("colorTheme")); + + verifyNoInteractions(lessCache); + verifyNoInteractions(colorThemeCache); + } + @Test public void clearCacheFromSkinWithRights() throws Exception { @@ -334,7 +348,7 @@ public void clearCacheFromSkinWithRights() throws Exception DocumentReference currentDocReference = new DocumentReference("wiki", "Space", "Page"); when(doc.getDocumentReference()).thenReturn(currentDocReference); - when(authorizationManager.hasAccess(Right.PROGRAM, authorReference, currentDocReference)).thenReturn(true); + when(authorizationManager.hasAccess(Right.PROGRAM)).thenReturn(true); SkinReference skinReference = mock(SkinReference.class); when(skinReferenceFactory.createReference("skin")).thenReturn(skinReference); @@ -358,7 +372,7 @@ public void clearCacheFromSkinWithoutRights() throws Exception DocumentReference currentDocReference = new DocumentReference("wiki", "Space", "Page"); when(doc.getDocumentReference()).thenReturn(currentDocReference); - when(authorizationManager.hasAccess(Right.PROGRAM, authorReference, currentDocReference)).thenReturn(false); + when(authorizationManager.hasAccess(Right.PROGRAM)).thenReturn(false); // Tests assertFalse(mocker.getComponentUnderTest().clearCacheFromSkin("skin")); @@ -368,4 +382,17 @@ public void clearCacheFromSkinWithoutRights() throws Exception verifyNoInteractions(colorThemeCache); } + @Test + public void clearCacheFromSkinWithException() throws Exception + { + when(this.authorizationManager.hasAccess(Right.PROGRAM)).thenReturn(true); + + LESSCompilerException exception = new LESSCompilerException("test"); + when(skinReferenceFactory.createReference("skin")).thenThrow(exception); + + assertFalse(this.mocker.getComponentUnderTest().clearCacheFromSkin("skin")); + + verifyNoInteractions(this.lessCache); + verifyNoInteractions(this.colorThemeCache); + } }
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-rp38-24m3-rx87ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-32972ghsaADVISORY
- github.com/xwiki/xwiki-platform/commit/91752122d8782f171f8728004a57bdaefc34253eghsax_refsource_MISCWEB
- github.com/xwiki/xwiki-platform/security/advisories/GHSA-rp38-24m3-rx87ghsax_refsource_CONFIRMWEB
- jira.xwiki.org/browse/XWIKI-22462ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.