VYPR
High severityNVD Advisory· Published Jun 13, 2025· Updated Jun 13, 2025

XWiki makes title of inaccessible pages available through the class property values REST API

CVE-2025-49584

Description

XWiki is a generic wiki platform. In XWiki Platform versions 10.9 through 16.4.6, 16.5.0-rc-1 through 16.10.2, and 17.0.0-rc-1, the title of every single page whose reference is known can be accessed through the REST API as long as an XClass with a page property is accessible, this is the default for an XWiki installation. This allows an attacker to get titles of pages whose reference is known, one title per request. This doesn't affect fully private wikis as the REST endpoint checks access rights on the XClass definition. The impact on confidentiality depends on the strategy for page names. By default, page names match the title, so the impact should be low but if page names are intentionally obfuscated because the titles are sensitive, the impact could be high. This has been fixed in XWiki 16.4.7, 16.10.3 and 17.0.0 by adding access control checks before getting the title of any page.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.xwiki.platform:xwiki-platform-rest-serverMaven
>= 10.9, < 16.4.716.4.7
org.xwiki.platform:xwiki-platform-rest-serverMaven
>= 16.5.0-rc-1, < 16.10.316.10.3
org.xwiki.platform:xwiki-platform-rest-serverMaven
>= 17.0.0-rc-1, < 17.0.017.0.0

Affected products

1

Patches

1
ee642f973a7c

XWIKI-22736: Improve right checks in property values provider

https://github.com/xwiki/xwiki-platformMichael HamannJan 20, 2025via ghsa
8 files changed · +209 74
  • xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/java/org/xwiki/rest/internal/resources/classes/AbstractDocumentListClassPropertyValuesProvider.java+6 1 modified
    @@ -39,6 +39,8 @@
     import org.xwiki.rest.model.jaxb.PropertyValue;
     import org.xwiki.rest.model.jaxb.PropertyValues;
     import org.xwiki.rest.resources.classes.ClassPropertyValuesProvider;
    +import org.xwiki.security.authorization.ContextualAuthorizationManager;
    +import org.xwiki.security.authorization.Right;
     
     import com.xpn.xwiki.XWiki;
     import com.xpn.xwiki.XWikiContext;
    @@ -61,6 +63,9 @@ public abstract class AbstractDocumentListClassPropertyValuesProvider<T extends
         @Inject
         protected IconManager iconManager;
     
    +    @Inject
    +    protected ContextualAuthorizationManager contextualAuthorizationManager;
    +
         @Inject
         @Named("compact")
         private EntityReferenceSerializer<String> compactSerializer;
    @@ -92,7 +97,7 @@ public PropertyValue getValue(ClassPropertyReference propertyReference, Object r
             DocumentReference documentReference = this.documentReferenceResolver.resolve(reference, propertyReference);
     
             PropertyValue propertyValue = null;
    -        if (exists(documentReference)) {
    +        if (this.contextualAuthorizationManager.hasAccess(Right.VIEW, documentReference) && exists(documentReference)) {
                 propertyValue = super.getValue(propertyReference, documentReference);
             }
     
    
  • xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/java/org/xwiki/rest/internal/resources/classes/GroupsClassPropertyValuesProvider.java+26 19 modified
    @@ -36,6 +36,7 @@
     import org.xwiki.query.QueryBuilder;
     import org.xwiki.rendering.syntax.Syntax;
     import org.xwiki.rest.model.jaxb.PropertyValues;
    +import org.xwiki.security.authorization.Right;
     import org.xwiki.wiki.user.UserScope;
     import org.xwiki.wiki.user.WikiUserManager;
     
    @@ -94,19 +95,22 @@ protected Map<String, Object> getIcon(DocumentReference groupReference)
         {
             Map<String, Object> icon = new HashMap<>();
             XWikiContext xcontext = this.xcontextProvider.get();
    -        try {
    -            XWikiDocument groupProfileDocument = xcontext.getWiki().getDocument(groupReference, xcontext);
    -            XWikiAttachment avatarAttachment = getFirstImageAttachment(groupProfileDocument, xcontext);
    -            if (avatarAttachment != null) {
    -                icon.put(IconManager.META_DATA_URL, xcontext.getWiki().getURL(avatarAttachment.getReference(),
    -                    "download", "width=30&height=30&keepAspectRatio=true", null, xcontext));
    -                icon.put(IconManager.META_DATA_ICON_SET_TYPE, IconType.IMAGE.name());
    +        if (this.contextualAuthorizationManager.hasAccess(Right.VIEW, groupReference)) {
    +            try {
    +                XWikiDocument groupProfileDocument = xcontext.getWiki().getDocument(groupReference, xcontext);
    +                XWikiAttachment avatarAttachment = getFirstImageAttachment(groupProfileDocument, xcontext);
    +                if (avatarAttachment != null) {
    +                    icon.put(IconManager.META_DATA_URL, xcontext.getWiki().getURL(avatarAttachment.getReference(),
    +                        "download", "width=30&height=30&keepAspectRatio=true", null, xcontext));
    +                    icon.put(IconManager.META_DATA_ICON_SET_TYPE, IconType.IMAGE.name());
    +                }
    +            } catch (XWikiException e) {
    +                this.logger.warn(
    +                    "Failed to read the avatar of group [{}]. Root cause is [{}]. Using the default avatar instead.",
    +                    groupReference.getName(), ExceptionUtils.getRootCauseMessage(e));
                 }
    -        } catch (XWikiException e) {
    -            this.logger.warn(
    -                "Failed to read the avatar of group [{}]. Root cause is [{}]. Using the default avatar instead.",
    -                groupReference.getName(), ExceptionUtils.getRootCauseMessage(e));
             }
    +
             if (!icon.containsKey(IconManager.META_DATA_URL)) {
                 try {
                     icon = this.iconManager.getMetaData(DEFAULT_ICON_NAME);
    @@ -132,14 +136,17 @@ private XWikiAttachment getFirstImageAttachment(XWikiDocument document, XWikiCon
         @Override
         protected String getLabel(DocumentReference groupReference, Object currentLabel)
         {
    -        try {
    -            XWikiContext xcontext = this.xcontextProvider.get();
    -            return xcontext.getWiki().getDocument(groupReference, xcontext).getRenderedTitle(Syntax.PLAIN_1_0,
    -                xcontext);
    -        } catch (XWikiException e) {
    -            this.logger.warn("Failed to get the title of group [{}]. Root cause is [{}].",
    -                this.entityReferenceSerializer.serialize(groupReference), ExceptionUtils.getRootCauseMessage(e));
    -            return super.getLabel(groupReference, currentLabel);
    +        if (this.contextualAuthorizationManager.hasAccess(Right.VIEW, groupReference)) {
    +            try {
    +                XWikiContext xcontext = this.xcontextProvider.get();
    +                return xcontext.getWiki().getDocument(groupReference, xcontext).getRenderedTitle(Syntax.PLAIN_1_0,
    +                    xcontext);
    +            } catch (XWikiException e) {
    +                this.logger.warn("Failed to get the title of group [{}]. Root cause is [{}].",
    +                    this.entityReferenceSerializer.serialize(groupReference), ExceptionUtils.getRootCauseMessage(e));
    +            }
             }
    +
    +        return super.getLabel(groupReference, currentLabel);
         }
     }
    
  • xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/java/org/xwiki/rest/internal/resources/classes/PageClassPropertyValuesProvider.java+18 11 modified
    @@ -37,6 +37,7 @@
     import org.xwiki.rendering.syntax.Syntax;
     import org.xwiki.rest.model.jaxb.PropertyValues;
     import org.xwiki.security.authorization.AuthorExecutor;
    +import org.xwiki.security.authorization.Right;
     
     import com.xpn.xwiki.XWiki;
     import com.xpn.xwiki.XWikiContext;
    @@ -95,17 +96,23 @@ protected Map<String, Object> getIcon(DocumentReference documentReference)
     
         private String getLabel(EntityReference entityReference)
         {
    -        String label;
    -        try {
    -            XWikiContext xcontext = this.xcontextProvider.get();
    -            XWikiDocument document;
    -            document = xcontext.getWiki().getDocument(entityReference, xcontext).getTranslatedDocument(xcontext);
    -            label = document.getRenderedTitle(Syntax.PLAIN_1_0, xcontext);
    -        } catch (XWikiException e) {
    -            this.logger.error("Error while loading the document [{}]. Root cause is [{}]", entityReference,
    -                ExceptionUtils.getRootCause(e));
    -            if (entityReference instanceof DocumentReference) {
    -                label = super.getLabel((DocumentReference) entityReference, "");
    +        String label = null;
    +
    +        if (this.contextualAuthorizationManager.hasAccess(Right.VIEW, entityReference)) {
    +            try {
    +                XWikiContext xcontext = this.xcontextProvider.get();
    +                XWikiDocument document;
    +                document = xcontext.getWiki().getDocument(entityReference, xcontext).getTranslatedDocument(xcontext);
    +                label = document.getRenderedTitle(Syntax.PLAIN_1_0, xcontext);
    +            } catch (XWikiException e) {
    +                this.logger.error("Error while loading the document [{}]. Root cause is [{}]", entityReference,
    +                    ExceptionUtils.getRootCauseMessage(e), e);
    +            }
    +        }
    +
    +        if (label == null) {
    +            if (entityReference instanceof DocumentReference documentReference) {
    +                label = super.getLabel(documentReference, "");
                 } else {
                     label = entityReference.getName();
                 }
    
  • xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/java/org/xwiki/rest/internal/resources/classes/UsersClassPropertyValuesProvider.java+18 13 modified
    @@ -35,6 +35,7 @@
     import org.xwiki.model.reference.DocumentReference;
     import org.xwiki.query.QueryBuilder;
     import org.xwiki.rest.model.jaxb.PropertyValues;
    +import org.xwiki.security.authorization.Right;
     import org.xwiki.user.UserConfiguration;
     import org.xwiki.user.UserProperties;
     import org.xwiki.user.UserPropertiesResolver;
    @@ -106,21 +107,25 @@ protected PropertyValues getAllowedValues(UsersClass propertyDefinition, int lim
         protected Map<String, Object> getIcon(DocumentReference userReference)
         {
             Map<String, Object> icon = new HashMap<>();
    -        XWikiContext xcontext = this.xcontextProvider.get();
    -        try {
    -            XWikiDocument userProfileDocument = xcontext.getWiki().getDocument(userReference, xcontext);
    -            String avatar = userProfileDocument.getStringValue("avatar");
    -            XWikiAttachment avatarAttachment = userProfileDocument.getAttachment(avatar);
    -            if (avatarAttachment != null && avatarAttachment.isImage(xcontext)) {
    -                icon.put(IconManager.META_DATA_URL, xcontext.getWiki().getURL(avatarAttachment.getReference(),
    -                    "download", "width=30&height=30&keepAspectRatio=true", null, xcontext));
    -                icon.put(IconManager.META_DATA_ICON_SET_TYPE, IconType.IMAGE.name());
    +
    +        if (this.contextualAuthorizationManager.hasAccess(Right.VIEW, userReference)) {
    +            XWikiContext xcontext = this.xcontextProvider.get();
    +            try {
    +                XWikiDocument userProfileDocument = xcontext.getWiki().getDocument(userReference, xcontext);
    +                String avatar = userProfileDocument.getStringValue("avatar");
    +                XWikiAttachment avatarAttachment = userProfileDocument.getAttachment(avatar);
    +                if (avatarAttachment != null && avatarAttachment.isImage(xcontext)) {
    +                    icon.put(IconManager.META_DATA_URL, xcontext.getWiki().getURL(avatarAttachment.getReference(),
    +                        "download", "width=30&height=30&keepAspectRatio=true", null, xcontext));
    +                    icon.put(IconManager.META_DATA_ICON_SET_TYPE, IconType.IMAGE.name());
    +                }
    +            } catch (XWikiException e) {
    +                this.logger.warn(
    +                    "Failed to read the avatar of user [{}]. Root cause is [{}]. Using the default avatar instead.",
    +                    userReference.getName(), ExceptionUtils.getRootCauseMessage(e));
                 }
    -        } catch (XWikiException e) {
    -            this.logger.warn(
    -                "Failed to read the avatar of user [{}]. Root cause is [{}]. Using the default avatar instead.",
    -                userReference.getName(), ExceptionUtils.getRootCauseMessage(e));
             }
    +
             if (!icon.containsKey(IconManager.META_DATA_URL)) {
                 try {
                     icon = this.iconManager.getMetaData(DEFAULT_ICON_NAME);
    
  • xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/test/java/org/xwiki/rest/internal/resources/classes/AbstractListClassPropertyValuesProviderTest.java+17 0 modified
    @@ -20,18 +20,21 @@
     package org.xwiki.rest.internal.resources.classes;
     
     import java.util.Arrays;
    +import java.util.Map;
     
     import javax.inject.Named;
     import javax.inject.Provider;
     
     import org.xwiki.component.manager.ComponentManager;
     import org.xwiki.component.util.DefaultParameterizedType;
    +import org.xwiki.icon.IconManager;
     import org.xwiki.model.reference.ClassPropertyReference;
     import org.xwiki.model.reference.DocumentReference;
     import org.xwiki.query.Query;
     import org.xwiki.query.QueryBuilder;
     import org.xwiki.query.QueryParameter;
     import org.xwiki.rest.resources.classes.ClassPropertyValuesProvider;
    +import org.xwiki.security.authorization.ContextualAuthorizationManager;
     import org.xwiki.test.junit5.mockito.InjectComponentManager;
     import org.xwiki.test.junit5.mockito.MockComponent;
     
    @@ -42,6 +45,7 @@
     import com.xpn.xwiki.objects.classes.ListClass;
     import com.xpn.xwiki.objects.classes.PropertyClass;
     
    +import static org.mockito.ArgumentMatchers.anyString;
     import static org.mockito.Mockito.mock;
     import static org.mockito.Mockito.when;
     
    @@ -69,16 +73,27 @@ public abstract class AbstractListClassPropertyValuesProviderTest
         @Named("usedValues")
         protected QueryBuilder<ListClass> usedValuesQueryBuilder;
     
    +    @MockComponent
    +    protected ContextualAuthorizationManager authorizationManager;
    +
         @InjectComponentManager
         protected ComponentManager componentManager;
     
    +    @MockComponent
    +    protected IconManager iconManager;
    +
    +    @MockComponent
    +    @Named("readonly")
    +    protected Provider<XWikiContext> readonlyXWikiContextProvider;
    +
         public void configure() throws Exception
         {
             Provider<XWikiContext> xcontextProvider = this.componentManager.getInstance(XWikiContext.TYPE_PROVIDER);
             BaseClass xclass = mock(BaseClass.class);
             DocumentReference authorReference = new DocumentReference("wiki", "Users", "Alice");
     
             when(xcontextProvider.get()).thenReturn(this.xcontext);
    +        when(this.readonlyXWikiContextProvider.get()).thenReturn(this.xcontext);
             when(this.xcontext.getWiki()).thenReturn(this.xwiki);
             when(this.classDocument.getXClass()).thenReturn(xclass);
             when(this.classDocument.getDocumentReference()).thenReturn(this.classReference);
    @@ -89,6 +104,8 @@ public void configure() throws Exception
             when(this.usedValuesQuery.bindValue("text")).thenReturn(queryParameter);
             when(queryParameter.anyChars()).thenReturn(queryParameter);
             when(queryParameter.literal("foo")).thenReturn(queryParameter);
    +
    +        when(this.iconManager.getMetaData(anyString())).thenAnswer(i -> mock(Map.class, i.<String>getArgument(0)));
         }
     
         protected void addProperty(String name, PropertyClass definition, boolean withQueryBuilders) throws Exception
    
  • xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/test/java/org/xwiki/rest/internal/resources/classes/GroupsClassPropertyValuesProviderTest.java+32 12 modified
    @@ -24,6 +24,8 @@
     
     import org.junit.jupiter.api.BeforeEach;
     import org.junit.jupiter.api.Test;
    +import org.junit.jupiter.params.ParameterizedTest;
    +import org.junit.jupiter.params.provider.ValueSource;
     import org.xwiki.model.reference.AttachmentReference;
     import org.xwiki.model.reference.ClassPropertyReference;
     import org.xwiki.model.reference.DocumentReference;
    @@ -41,8 +43,10 @@
     import com.xpn.xwiki.objects.classes.GroupsClass;
     
     import static org.junit.jupiter.api.Assertions.assertEquals;
    -import static org.junit.jupiter.api.Assertions.assertTrue;
    +import static org.junit.jupiter.api.Assertions.assertInstanceOf;
    +import static org.mockito.ArgumentMatchers.any;
     import static org.mockito.Mockito.mock;
    +import static org.mockito.Mockito.mockingDetails;
     import static org.mockito.Mockito.times;
     import static org.mockito.Mockito.verify;
     import static org.mockito.Mockito.when;
    @@ -53,7 +57,7 @@
      * @version $Id$
      */
     @ComponentTest
    -public class GroupsClassPropertyValuesProviderTest extends AbstractListClassPropertyValuesProviderTest
    +class GroupsClassPropertyValuesProviderTest extends AbstractListClassPropertyValuesProviderTest
     {
         @InjectMockComponents
         private GroupsClassPropertyValuesProvider provider;
    @@ -73,11 +77,13 @@ public void configure() throws Exception
                 .thenReturn("url/to/noavatar.png");
         }
     
    -    @Test
    -    public void getValuesLocal() throws Exception
    +    @ParameterizedTest
    +    @ValueSource(booleans = { true, false })
    +    void getValuesLocal(boolean hasAccess) throws Exception
         {
             when(this.wikiUserManager.getUserScope(this.classReference.getWikiReference().getName()))
                 .thenReturn(UserScope.LOCAL_ONLY);
    +        when(this.authorizationManager.hasAccess(any(), any())).thenReturn(hasAccess);
     
             DocumentReference devsReference = new DocumentReference("wiki", "Groups", "Devs");
             XWikiDocument devsProfile = mock(XWikiDocument.class, "devs");
    @@ -103,18 +109,32 @@ public void getValuesLocal() throws Exception
     
             assertEquals(2, values.getPropertyValues().size());
     
    -        assertEquals("Developers", values.getPropertyValues().get(0).getMetaData().get("label"));
    -        assertTrue(values.getPropertyValues().get(0).getMetaData().get("icon") instanceof Map);
    -
    -        assertEquals("Administrators", values.getPropertyValues().get(1).getMetaData().get("label"));
    -        assertTrue(values.getPropertyValues().get(1).getMetaData().get("icon") instanceof Map);
    +        Object devsLabel = values.getPropertyValues().get(0).getMetaData().get("label");
    +        if (hasAccess) {
    +            assertEquals("Developers", devsLabel);
    +        } else {
    +            assertEquals("Devs", devsLabel);
    +        }
    +        assertInstanceOf(Map.class, values.getPropertyValues().get(0).getMetaData().get("icon"));
    +
    +        Object adminLabel = values.getPropertyValues().get(1).getMetaData().get("label");
    +        if (hasAccess) {
    +            assertEquals("Administrators", adminLabel);
    +        } else {
    +            assertEquals("Admins", adminLabel);
    +        }
    +        assertInstanceOf(Map.class, values.getPropertyValues().get(1).getMetaData().get("icon"));
             Map icon = (Map) values.getPropertyValues().get(1).getMetaData().get("icon");
    -        assertEquals("url/to/admins/image", icon.get("url"));
    -        assertEquals("IMAGE", icon.get("iconSetType"));
    +        if (hasAccess) {
    +            assertEquals("url/to/admins/image", icon.get("url"));
    +            assertEquals("IMAGE", icon.get("iconSetType"));
    +        } else {
    +            assertEquals("group", mockingDetails(icon).getMockCreationSettings().getMockName().toString());
    +        }
         }
     
         @Test
    -    public void getValuesLocalAndGlobal() throws Exception
    +    void getValuesLocalAndGlobal() throws Exception
         {
             // We can have local groups.
             when(this.wikiUserManager.getUserScope(this.classReference.getWikiReference().getName()))
    
  • xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/test/java/org/xwiki/rest/internal/resources/classes/PageClassPropertyValuesProviderTest.java+76 12 modified
    @@ -24,24 +24,30 @@
     import java.util.Map;
     
     import org.junit.jupiter.api.BeforeEach;
    -import org.junit.jupiter.api.Test;
    +import org.junit.jupiter.params.ParameterizedTest;
    +import org.junit.jupiter.params.provider.ValueSource;
    +import org.xwiki.model.reference.ClassPropertyReference;
     import org.xwiki.model.reference.DocumentReference;
     import org.xwiki.model.reference.EntityReference;
     import org.xwiki.model.reference.SpaceReference;
     import org.xwiki.model.reference.WikiReference;
     import org.xwiki.query.Query;
     import org.xwiki.rendering.syntax.Syntax;
    +import org.xwiki.rest.model.jaxb.PropertyValue;
     import org.xwiki.rest.model.jaxb.PropertyValues;
    +import org.xwiki.security.authorization.Right;
     import org.xwiki.test.junit5.mockito.ComponentTest;
     import org.xwiki.test.junit5.mockito.InjectMockComponents;
     import org.xwiki.test.junit5.mockito.MockComponent;
     
     import com.xpn.xwiki.XWiki;
     import com.xpn.xwiki.doc.XWikiDocument;
     import com.xpn.xwiki.objects.classes.PageClass;
    +import com.xpn.xwiki.test.reference.ReferenceComponentList;
     
     import static org.junit.jupiter.api.Assertions.assertEquals;
     import static org.junit.jupiter.api.Assertions.assertTrue;
    +import static org.mockito.ArgumentMatchers.any;
     import static org.mockito.Mockito.mock;
     import static org.mockito.Mockito.when;
     import static org.xwiki.rest.internal.resources.classes.AbstractClassPropertyValuesProvider.META_DATA_ICON;
    @@ -53,14 +59,16 @@
      * @since 10.6
      */
     @ComponentTest
    -public class PageClassPropertyValuesProviderTest extends AbstractListClassPropertyValuesProviderTest
    +@ReferenceComponentList
    +class PageClassPropertyValuesProviderTest extends AbstractListClassPropertyValuesProviderTest
     {
         @InjectMockComponents
         private PageClassPropertyValuesProvider provider;
     
         @MockComponent
         private PageClass pageClass;
     
    +    @Override
         @BeforeEach
         public void configure() throws Exception
         {
    @@ -69,9 +77,12 @@ public void configure() throws Exception
             when(this.pageClass.getOwnerDocument()).thenReturn(this.classDocument);
         }
     
    -    @Test
    -    public void getValues() throws Exception
    +    @ParameterizedTest
    +    @ValueSource(booleans = { true, false })
    +    void getValues(boolean hasAccess) throws Exception
         {
    +        when(this.authorizationManager.hasAccess(any(), any())).thenReturn(hasAccess);
    +
             WikiReference wikiRef = new WikiReference("wiki");
             SpaceReference space1Ref = new SpaceReference("space1", wikiRef);
             SpaceReference space2Ref = new SpaceReference("space2", space1Ref);
    @@ -97,14 +108,22 @@ public void getValues() throws Exception
             assertEquals(1, values.getPropertyValues().size());
     
             Map<String, Object> metadata = values.getPropertyValues().get(0).getMetaData();
    -        assertEquals("Space 1 / Space 2", metadata.get("hint"));
    -        assertEquals("Page", metadata.get("label"));
    +        if (hasAccess) {
    +            assertEquals("Space 1 / Space 2", metadata.get("hint"));
    +            assertEquals("Page", metadata.get("label"));
    +        } else {
    +            assertEquals("space1 / space2", metadata.get("hint"));
    +            assertEquals("page", metadata.get("label"));
    +        }
             assertTrue(metadata.containsKey(META_DATA_ICON));
         }
     
    -    @Test
    -    public void getValuesWithTerminalPage() throws Exception
    +    @ParameterizedTest
    +    @ValueSource(booleans = { true, false })
    +    void getValuesWithTerminalPage(boolean hasAccess) throws Exception
         {
    +        when(this.authorizationManager.hasAccess(any(), any())).thenReturn(hasAccess);
    +
             WikiReference wikiRef = new WikiReference("wiki");
             SpaceReference space1Ref = new SpaceReference("space1", wikiRef);
             SpaceReference space2Ref = new SpaceReference("space2", space1Ref);
    @@ -135,13 +154,58 @@ public void getValuesWithTerminalPage() throws Exception
             assertEquals(2, values.getPropertyValues().size());
     
             Map<String, Object> metadata = values.getPropertyValues().get(0).getMetaData();
    -        assertEquals("Space 1 / Page 2", metadata.get("hint"));
    -        assertEquals("Page 1", metadata.get("label"));
    +        if (hasAccess) {
    +            assertEquals("Space 1 / Page 2", metadata.get("hint"));
    +            assertEquals("Page 1", metadata.get("label"));
    +        } else {
    +            assertEquals("space1 / space2", metadata.get("hint"));
    +            assertEquals("page", metadata.get("label"));
    +        }
             assertTrue(metadata.containsKey(META_DATA_ICON));
     
             metadata = values.getPropertyValues().get(1).getMetaData();
    -        assertEquals("Space 1", metadata.get("hint"));
    -        assertEquals("Page 2", metadata.get("label"));
    +        if (hasAccess) {
    +            assertEquals("Space 1", metadata.get("hint"));
    +            assertEquals("Page 2", metadata.get("label"));
    +        } else {
    +            assertEquals("space1", metadata.get("hint"));
    +            assertEquals("space2", metadata.get("label"));
    +        }
             assertTrue(metadata.containsKey(META_DATA_ICON));
         }
    +
    +    @ParameterizedTest
    +    @ValueSource(booleans = { true, false })
    +    void getValue(boolean hasAccess) throws Exception
    +    {
    +        String spaceName = "DocumentSpace";
    +        String pageName = "DocumentPage";
    +        String stringReference = "%s.%s".formatted(spaceName, pageName);
    +        DocumentReference documentReference =
    +            new DocumentReference(this.classReference.getWikiReference().getName(), spaceName, pageName);
    +        when(this.authorizationManager.hasAccess(Right.VIEW, documentReference)).thenReturn(hasAccess);
    +
    +        XWikiDocument document = mock();
    +        when(this.xwiki.getDocument(documentReference, this.xcontext)).thenReturn(document);
    +        when(this.xwiki.getDocument((EntityReference) documentReference, this.xcontext)).thenReturn(document);
    +
    +        String title = "Title";
    +        when(document.getRenderedTitle(Syntax.PLAIN_1_0, this.xcontext)).thenReturn(title);
    +        when(document.getTranslatedDocument(this.xcontext)).thenReturn(document);
    +        when(this.xwiki.exists(documentReference, this.xcontext)).thenReturn(true);
    +
    +        String propertyName = "propertyName";
    +        ClassPropertyReference propertyReference = new ClassPropertyReference(propertyName, this.classReference);
    +        addProperty(propertyName, new PageClass(), false);
    +
    +        PropertyValue value = this.provider.getValue(propertyReference, stringReference);
    +
    +        assertEquals(stringReference, value.getValue());
    +        if (!hasAccess) {
    +            assertEquals(Map.of(), value.getMetaData());
    +        } else {
    +            assertEquals(title, value.getMetaData().get("label"));
    +            assertEquals(spaceName, value.getMetaData().get("hint"));
    +        }
    +    }
     }
    
  • xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/test/java/org/xwiki/rest/internal/resources/classes/UsersClassPropertyValuesProviderTest.java+16 6 modified
    @@ -28,6 +28,8 @@
     
     import org.junit.jupiter.api.BeforeEach;
     import org.junit.jupiter.api.Test;
    +import org.junit.jupiter.params.ParameterizedTest;
    +import org.junit.jupiter.params.provider.ValueSource;
     import org.xwiki.model.reference.AttachmentReference;
     import org.xwiki.model.reference.ClassPropertyReference;
     import org.xwiki.model.reference.DocumentReference;
    @@ -54,6 +56,7 @@
     import static org.junit.jupiter.api.Assertions.assertTrue;
     import static org.mockito.ArgumentMatchers.any;
     import static org.mockito.Mockito.mock;
    +import static org.mockito.Mockito.mockingDetails;
     import static org.mockito.Mockito.never;
     import static org.mockito.Mockito.times;
     import static org.mockito.Mockito.verify;
    @@ -96,15 +99,18 @@ public void configure() throws Exception
                 .thenReturn("url/to/noavatar.png");
         }
     
    -    @Test
    -    public void getValuesLocal() throws Exception
    +    @ParameterizedTest
    +    @ValueSource(booleans = { true, false })
    +    void getValuesLocal(boolean hasAccess) throws Exception
         {
    +        when(this.authorizationManager.hasAccess(any(), any())).thenReturn(hasAccess);
    +
             when(this.wikiUserManager.getUserScope(this.classReference.getWikiReference().getName()))
                 .thenReturn(UserScope.LOCAL_ONLY);
     
             DocumentReference aliceReference = new DocumentReference("wiki", "Users", "Alice");
             when(this.allowedValuesQuery.execute())
    -            .thenReturn(Collections.singletonList(new Object[]{ aliceReference, " Alice One " }));
    +            .thenReturn(Collections.singletonList(new Object[] { aliceReference, " Alice One " }));
             when(this.xcontext.getWiki().getDocument(aliceReference, this.xcontext))
                 .thenReturn(mock(XWikiDocument.class, "alice"));
     
    @@ -114,7 +120,7 @@ public void getValuesLocal() throws Exception
             DocumentReference bobReference = new DocumentReference("wiki", "Users", "Bob");
             when(this.usedValuesQuery.getFilters()).thenReturn(filters);
             when(this.usedValuesQuery.execute())
    -            .thenReturn(Arrays.asList(new Object[]{ bobReference, 17L }, new Object[]{ aliceReference, 3L }));
    +            .thenReturn(Arrays.asList(new Object[] { bobReference, 17L }, new Object[] { aliceReference, 3L }));
     
             EntityReferenceSerializer<String> compactSerializer =
                 this.componentManager.getInstance(EntityReferenceSerializer.TYPE_STRING, "compact");
    @@ -153,8 +159,12 @@ public void getValuesLocal() throws Exception
             assertEquals(17L, values.getPropertyValues().get(1).getMetaData().get("count"));
             assertTrue(values.getPropertyValues().get(1).getMetaData().get("icon") instanceof Map);
             Map icon = (Map) values.getPropertyValues().get(1).getMetaData().get("icon");
    -        assertEquals("url/to/bob/avatar", icon.get("url"));
    -        assertEquals("IMAGE", icon.get("iconSetType"));
    +        if (hasAccess) {
    +            assertEquals("url/to/bob/avatar", icon.get("url"));
    +            assertEquals("IMAGE", icon.get("iconSetType"));
    +        } else {
    +            assertEquals("user", mockingDetails(icon).getMockCreationSettings().getMockName().toString());
    +        }
             assertEquals("url/to/bob", values.getPropertyValues().get(1).getMetaData().get("url"));
     
             verify(this.allowedValuesQuery, never()).setWiki(any(String.class));
    

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.