VYPR
Moderate severityNVD Advisory· Published Apr 30, 2025· Updated Apr 30, 2025

XWiki missing authorization when accessing the wiki level attachments list and metadata via REST API

CVE-2025-46554

Description

XWiki is a generic wiki platform. In versions starting from 1.8.1 to before 14.10.22, from 15.0-rc-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.7.0, anyone can access the metadata of any attachment in the wiki using the wiki attachment REST endpoint. There is no filtering for the results depending on current user rights, meaning an unauthenticated user could exploit this even in a private wiki. This issue has been patched in versions 14.10.22, 15.10.12, 16.4.3, and 16.7.0.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.xwiki.platform:xwiki-platform-rest-serverMaven
>= 1.8.1, < 14.10.2214.10.22
org.xwiki.platform:xwiki-platform-rest-serverMaven
>= 15.0-rc-1, < 15.10.1215.10.12
org.xwiki.platform:xwiki-platform-rest-serverMaven
>= 16.0.0-rc-1, < 16.4.316.4.3
org.xwiki.platform:xwiki-platform-rest-serverMaven
>= 16.5.0-rc-1, < 16.7.016.7.0

Affected products

1

Patches

3
c02ce7843a39

XWIKI-22424: Improve attachment filtering

https://github.com/xwiki/xwiki-platformThomas MortagneAug 19, 2024via ghsa
1 file changed · +0 5
  • xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/java/org/xwiki/rest/internal/resources/attachments/AttachmentResourceImpl.java+0 5 modified
    @@ -22,7 +22,6 @@
     import java.io.ByteArrayInputStream;
     import java.io.InputStream;
     
    -import javax.inject.Inject;
     import javax.inject.Named;
     import javax.ws.rs.WebApplicationException;
     import javax.ws.rs.core.Response;
    @@ -34,7 +33,6 @@
     import org.xwiki.rest.internal.Utils;
     import org.xwiki.rest.internal.resources.BaseAttachmentsResource;
     import org.xwiki.rest.resources.attachments.AttachmentResource;
    -import org.xwiki.security.authorization.ContextualAuthorizationManager;
     import org.xwiki.security.authorization.Right;
     
     import com.xpn.xwiki.XWikiException;
    @@ -49,9 +47,6 @@
     @Named("org.xwiki.rest.internal.resources.attachments.AttachmentResourceImpl")
     public class AttachmentResourceImpl extends BaseAttachmentsResource implements AttachmentResource
     {
    -    @Inject
    -    private ContextualAuthorizationManager authorization;
    -
         @Override
         public Response getAttachment(String wikiName, String spaceName, String pageName, String attachmentName)
             throws XWikiRestException
    
a43e933ddeda

XWIKI-22424: Improve attachment filtering

https://github.com/xwiki/xwiki-platformThomas MortagneAug 16, 2024via ghsa
5 files changed · +57 7
  • xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/java/org/xwiki/rest/internal/resources/attachments/AttachmentsResourceImpl.java+0 4 modified
    @@ -49,7 +49,6 @@
     import org.xwiki.rest.model.jaxb.Attachments;
     import org.xwiki.rest.resources.attachments.AttachmentResource;
     import org.xwiki.rest.resources.attachments.AttachmentsResource;
    -import org.xwiki.security.authorization.ContextualAuthorizationManager;
     import org.xwiki.security.authorization.Right;
     
     import com.xpn.xwiki.XWikiException;
    @@ -64,9 +63,6 @@ public class AttachmentsResourceImpl extends BaseAttachmentsResource implements
     {
         private static final String NAME = "name";
     
    -    @Inject
    -    private ContextualAuthorizationManager authorization;
    -
         @Inject
         private Container container;
     
    
  • xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/main/java/org/xwiki/rest/internal/resources/BaseAttachmentsResource.java+10 1 modified
    @@ -56,6 +56,8 @@
     import org.xwiki.rest.internal.Utils;
     import org.xwiki.rest.model.jaxb.Attachment;
     import org.xwiki.rest.model.jaxb.Attachments;
    +import org.xwiki.security.authorization.ContextualAuthorizationManager;
    +import org.xwiki.security.authorization.Right;
     import org.xwiki.user.UserReferenceResolver;
     
     import com.xpn.xwiki.XWiki;
    @@ -113,6 +115,9 @@ public boolean isAlreadyExisting()
             FILTER_TO_QUERY.put("author", "attachment.author");
         }
     
    +    @Inject
    +    protected ContextualAuthorizationManager authorization;
    +
         @Inject
         private ModelFactory modelFactory;
     
    @@ -157,15 +162,19 @@ protected Attachments getAttachments(EntityReference scope, Map<String, String>
     
                 List<Object> queryResults = getAttachmentsQuery(scope, filters).setLimit(limit).setOffset(offset).execute();
                 attachments.withAttachments(queryResults.stream().map(this::processAttachmentsQueryResult)
    +                // Apply passed filters
                     .filter(getFileTypeFilter(filters.getOrDefault(FILTER_FILE_TYPES, "")))
    +                // Filter out attachments the current user is not allowed to see
    +                .filter(a -> authorization.hasAccess(Right.VIEW, a.getReference()))
    +                // Convert XWikiAttachment to REST Attachment
                     .map(xwikiAttachment -> toRestAttachment(xwikiAttachment, withPrettyNames))
                     .toList());
             } catch (QueryException e) {
                 throw new XWikiRestException(e);
             } finally {
                 xcontext.setWikiId(database);
             }
    -
    +        
             return attachments;
         }
     
    
  • xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/test/java/org/xwiki/rest/internal/resources/attachments/AttachmentsResourceImplTest.java+3 0 modified
    @@ -66,6 +66,7 @@
     import static org.junit.jupiter.api.Assertions.assertThrows;
     import static org.mockito.ArgumentMatchers.any;
     import static org.mockito.ArgumentMatchers.eq;
    +import static org.mockito.ArgumentMatchers.same;
     import static org.mockito.Mockito.doThrow;
     import static org.mockito.Mockito.mock;
     import static org.mockito.Mockito.times;
    @@ -157,6 +158,8 @@ void getAttachments() throws Exception
                 new Object[] {"Path.To", "Page", "1.3", imageAttachment});
             when(query.execute()).thenReturn(results);
     
    +        when(this.authorization.hasAccess(same(Right.VIEW), any())).thenReturn(true);
    +
             DocumentReference documentReference = new DocumentReference("test", Arrays.asList("Path", "To"), "Page");
             when(this.defaultSpaceReferenceResover.resolve(eq("Path.To"), any()))
                 .thenReturn(documentReference.getLastSpaceReference());
    
  • xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/test/java/org/xwiki/rest/internal/resources/spaces/SpaceAttachmentsResourceImplTest.java+21 1 modified
    @@ -19,17 +19,22 @@
      */
     package org.xwiki.rest.internal.resources.spaces;
     
    +import java.util.Arrays;
     import java.util.Collections;
     import java.util.List;
     
     import org.junit.jupiter.api.BeforeEach;
     import org.junit.jupiter.api.Test;
    +import org.xwiki.model.reference.AttachmentReference;
     import org.xwiki.model.reference.SpaceReference;
     import org.xwiki.query.Query;
     import org.xwiki.rest.internal.resources.AbstractAttachmentsResourceTest;
     import org.xwiki.rest.model.jaxb.Attachment;
     import org.xwiki.rest.model.jaxb.Attachments;
    +import org.xwiki.security.authorization.ContextualAuthorizationManager;
    +import org.xwiki.security.authorization.Right;
     import org.xwiki.test.junit5.mockito.InjectMockComponents;
    +import org.xwiki.test.junit5.mockito.MockComponent;
     
     import com.xpn.xwiki.doc.XWikiAttachment;
     import com.xpn.xwiki.test.junit5.mockito.OldcoreTest;
    @@ -52,6 +57,9 @@ class SpaceAttachmentsResourceImplTest extends AbstractAttachmentsResourceTest
         @InjectMockComponents
         private SpaceAttachmentsResourceImpl spaceAttachmentsResource;
     
    +    @MockComponent
    +    private ContextualAuthorizationManager authorization;
    +
         @BeforeEach
         @Override
         public void setUp() throws Exception
    @@ -74,7 +82,17 @@ void getAttachments() throws Exception
             when(query.setLimit(5)).thenReturn(query);
     
             XWikiAttachment xwikiAttachment = mock(XWikiAttachment.class);
    -        List<Object> results = Collections.singletonList(new Object[] {"Path.To", "Page", "1.3", xwikiAttachment});
    +        AttachmentReference xwikiAttachmentReference = mock(AttachmentReference.class, "image");
    +        when(xwikiAttachment.getReference()).thenReturn(xwikiAttachmentReference);
    +        when(this.authorization.hasAccess(Right.VIEW, xwikiAttachmentReference)).thenReturn(true);
    +
    +        XWikiAttachment forbiddenAttachment = mock(XWikiAttachment.class);
    +        AttachmentReference forbiddenAttachmentReference = mock(AttachmentReference.class, "forbidden");
    +        when(forbiddenAttachment.getReference()).thenReturn(forbiddenAttachmentReference);
    +        when(this.authorization.hasAccess(Right.VIEW, forbiddenAttachmentReference)).thenReturn(false);
    +
    +        List<Object> results = Arrays.asList(new Object[] {"Path.To", "Page", "1.3", xwikiAttachment},
    +            new Object[] {"Path.To", "ForbiddenPage", "1.3", forbiddenAttachment});
             when(query.execute()).thenReturn(results);
     
             SpaceReference spaceReference = new SpaceReference("test", "Path", "To");
    @@ -89,6 +107,8 @@ void getAttachments() throws Exception
                 this.spaceAttachmentsResource.getAttachments("test", "Path/spaces/To", "", "xyz", "", "", 10, 5, false);
     
             verify(query).bindValue("localSpaceReference", "Path.To");
    +        verify(this.authorization).hasAccess(Right.VIEW, xwikiAttachmentReference);
    +        verify(this.authorization).hasAccess(Right.VIEW, forbiddenAttachmentReference);
     
             assertEquals(Collections.singletonList(attachment), attachments.getAttachments());
         }
    
  • xwiki-platform-core/xwiki-platform-rest/xwiki-platform-rest-server/src/test/java/org/xwiki/rest/internal/resources/wikis/WikiAttachmentsResourceImplTest.java+23 1 modified
    @@ -19,17 +19,22 @@
      */
     package org.xwiki.rest.internal.resources.wikis;
     
    +import java.util.Arrays;
     import java.util.Collections;
     import java.util.List;
     
     import org.junit.jupiter.api.BeforeEach;
     import org.junit.jupiter.api.Test;
    +import org.xwiki.model.reference.AttachmentReference;
     import org.xwiki.model.reference.SpaceReference;
     import org.xwiki.query.Query;
     import org.xwiki.rest.internal.resources.AbstractAttachmentsResourceTest;
     import org.xwiki.rest.model.jaxb.Attachment;
     import org.xwiki.rest.model.jaxb.Attachments;
    +import org.xwiki.security.authorization.ContextualAuthorizationManager;
    +import org.xwiki.security.authorization.Right;
     import org.xwiki.test.junit5.mockito.InjectMockComponents;
    +import org.xwiki.test.junit5.mockito.MockComponent;
     
     import com.xpn.xwiki.doc.XWikiAttachment;
     import com.xpn.xwiki.test.junit5.mockito.OldcoreTest;
    @@ -38,6 +43,7 @@
     import static org.mockito.ArgumentMatchers.any;
     import static org.mockito.ArgumentMatchers.eq;
     import static org.mockito.Mockito.mock;
    +import static org.mockito.Mockito.verify;
     import static org.mockito.Mockito.when;
     
     /**
    @@ -51,6 +57,9 @@ class WikiAttachmentsResourceImplTest extends AbstractAttachmentsResourceTest
         @InjectMockComponents
         private WikiAttachmentsResourceImpl wikiAttachmentsResource;
     
    +    @MockComponent
    +    private ContextualAuthorizationManager authorization;
    +
         @BeforeEach
         @Override
         public void setUp() throws Exception
    @@ -71,7 +80,17 @@ void getAttachments() throws Exception
             when(query.setLimit(10)).thenReturn(query);
     
             XWikiAttachment xwikiAttachment = mock(XWikiAttachment.class);
    -        List<Object> results = Collections.singletonList(new Object[] {"Path.To", "Page", "1.3", xwikiAttachment});
    +        AttachmentReference xwikiAttachmentReference = mock(AttachmentReference.class, "image");
    +        when(xwikiAttachment.getReference()).thenReturn(xwikiAttachmentReference);
    +        when(this.authorization.hasAccess(Right.VIEW, xwikiAttachmentReference)).thenReturn(true);
    +
    +        XWikiAttachment forbiddenAttachment = mock(XWikiAttachment.class);
    +        AttachmentReference forbiddenAttachmentReference = mock(AttachmentReference.class, "forbidden");
    +        when(forbiddenAttachment.getReference()).thenReturn(forbiddenAttachmentReference);
    +        when(this.authorization.hasAccess(Right.VIEW, forbiddenAttachmentReference)).thenReturn(false);
    +
    +        List<Object> results = Arrays.asList(new Object[] {"Path.To", "Page", "1.3", xwikiAttachment},
    +            new Object[] {"Path.To", "ForbiddenPage", "1.3", forbiddenAttachment});
             when(query.execute()).thenReturn(results);
     
             when(this.defaultSpaceReferenceResover.resolve(eq("Path.To"), any()))
    @@ -84,6 +103,9 @@ void getAttachments() throws Exception
             Attachments attachments =
                 this.wikiAttachmentsResource.getAttachments("test", "", "", "abc", "", "", 0, 10, true);
     
    +        verify(this.authorization).hasAccess(Right.VIEW, xwikiAttachmentReference);
    +        verify(this.authorization).hasAccess(Right.VIEW, forbiddenAttachmentReference);
    +
             assertEquals(Collections.singletonList(attachment), attachments.getAttachments());
         }
     }
    
37ecea84fdd0

XWIKI-4135: Component override support does not work

https://github.com/xwiki/xwiki-platformtmortagneAug 8, 2009via ghsa
2 files changed · +15 7
  • xwiki-component/xwiki-component-default/src/main/java/org/xwiki/component/annotation/ComponentAnnotationLoader.java+2 2 modified
    @@ -105,11 +105,11 @@ public void initialize(ComponentManager manager, ClassLoader classLoader)
                             if (descriptorMap.containsKey(roleHint)) {
                                 // Is the component in the override list?
                                 ComponentDescriptor existingDescriptor = descriptorMap.get(roleHint);
    -                            if (!componentOverrideClassNames.contains(existingDescriptor.getImplementation())) {
    +                            if (!componentOverrideClassNames.contains(existingDescriptor.getImplementation().getName())) {
                                     descriptorMap.put(new RoleHint(componentRoleClass, descriptor.getRoleHint()),
                                         descriptor);
     
    -                                if (!componentOverrideClassNames.contains(descriptor.getImplementation())) {
    +                                if (!componentOverrideClassNames.contains(descriptor.getImplementation().getName())) {
                                         getLogger().warn(
                                             "Component [" + existingDescriptor.getImplementation().getName()
                                                 + "] is being overwritten by component ["
    
  • xwiki-component/xwiki-component-default/src/test/java/org/xwiki/component/annotation/ComponentAnnotationLoaderTest.java+13 5 modified
    @@ -26,8 +26,10 @@
     import org.hamcrest.Factory;
     import org.hamcrest.Matcher;
     import org.hamcrest.TypeSafeMatcher;
    +import org.hamcrest.core.IsNot;
     import org.jmock.Expectations;
     import org.jmock.Mockery;
    +import org.junit.After;
     import org.junit.Assert;
     import org.junit.Test;
     import org.xwiki.component.descriptor.ComponentDescriptor;
    @@ -80,9 +82,9 @@ public void testFindComponentRoleClasses()
     
         public static class ComponentDescriptorMatcher extends TypeSafeMatcher<ComponentDescriptor>
         {
    -        private String implementation;
    +        private Class<?> implementation;
             
    -        public ComponentDescriptorMatcher(String implementation)
    +        public ComponentDescriptorMatcher(Class<?> implementation)
             {
                 this.implementation = implementation;
             }
    @@ -100,11 +102,17 @@ public void describeTo(Description description)
         }
         
         @Factory
    -    public static Matcher<ComponentDescriptor> aComponentDescriptorWithImplementation(String implementation)
    +    public static Matcher<ComponentDescriptor> aComponentDescriptorWithImplementation(Class<?> implementation)
         {
             return new ComponentDescriptorMatcher(implementation);
         }
     
    +    @After
    +    public void tearDown() throws Exception
    +    {
    +        this.context.assertIsSatisfied();
    +    }
    +    
         /**
          * Verify that when there are several component implementations for the same role/hint then
          * component implementations defined in META-INF/component-overrides.txt are used in priority.
    @@ -116,8 +124,8 @@ public void testOverrides() throws Exception
         	final ComponentManager mockManager = this.context.mock(ComponentManager.class);
     
         	this.context.checking(new Expectations() {{
    -    	    allowing(mockManager).registerComponent(with(any(ComponentDescriptor.class)));
    -    	    oneOf(mockManager).registerComponent(with(aComponentDescriptorWithImplementation(OverrideRole.class.getName())));
    +                allowing(mockManager).registerComponent(
    +                    with(new IsNot<ComponentDescriptor>(aComponentDescriptorWithImplementation(SimpleRole.class))));
             }});
     
         	loader.initialize(mockManager, this.getClass().getClassLoader());
    

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

8

News mentions

0

No linked articles in our index yet.