VYPR
Moderate severityNVD Advisory· Published Mar 2, 2023· Updated Mar 5, 2025

XWiki Platform allows macro execution as any user without programming rights through the context macro

CVE-2023-26056

Description

XWiki Platform is a generic wiki platform. Starting in version 3.0-milestone-1, it's possible to execute a script with the right of another user, provided the target user does not have programming right. The problem has been patched in XWiki 14.8-rc-1, 14.4.5, and 13.10.10. There are no known workarounds for this issue.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.xwiki.platform:xwiki-platform-rendering-macro-contextMaven
>= 3.0-milestone-1, < 13.10.1013.10.10
org.xwiki.platform:xwiki-platform-rendering-macro-contextMaven
>= 14.0-rc-1, < 14.4.514.4.5
org.xwiki.platform:xwiki-platform-rendering-macro-contextMaven
>= 14.5, < 14.8-rc-114.8-rc-1

Affected products

1

Patches

3
4b75f212c2dd

XWIKI-19856: Bad execution setup on the context macro

https://github.com/xwiki/xwiki-platformThomas MortagneSep 9, 2022via ghsa
2 files changed · +12 5
  • xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-context/src/main/java/org/xwiki/rendering/internal/macro/context/ContextMacro.java+2 0 modified
    @@ -169,6 +169,8 @@ public List<Block> execute(ContextMacroParameters parameters, String content, Ma
             // Reuse the very generic async rendering framework (even if we don't do async and caching) since it's taking
             // care of many other things
             BlockAsyncRendererConfiguration configuration = createBlockAsyncRendererConfiguration(null, xdom, context);
    +        configuration.setAsyncAllowed(false);
    +        configuration.setCacheAllowed(false);
     
             Map<String, Object> backupObjects = new HashMap<>();
             try {
    
  • xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-context/src/test/java/org/xwiki/rendering/internal/macro/context/ContextMacroTest.java+10 5 modified
    @@ -22,7 +22,6 @@
     import java.util.Arrays;
     import java.util.Collections;
     
    -import javax.inject.Inject;
     import javax.inject.Named;
     
     import org.junit.jupiter.api.BeforeEach;
    @@ -51,8 +50,10 @@
     import org.xwiki.test.TestEnvironment;
     import org.xwiki.test.annotation.ComponentList;
     import org.xwiki.test.junit5.mockito.ComponentTest;
    +import org.xwiki.test.junit5.mockito.InjectComponentManager;
     import org.xwiki.test.junit5.mockito.InjectMockComponents;
     import org.xwiki.test.junit5.mockito.MockComponent;
    +import org.xwiki.test.mockito.MockitoComponentManager;
     
     import static org.junit.jupiter.api.Assertions.assertEquals;
     import static org.junit.jupiter.api.Assertions.fail;
    @@ -80,9 +81,6 @@ class ContextMacroTest
     
         private static final DocumentReference SOURCE_REFERENCE = new DocumentReference("wiki", "space", "source");
     
    -    @Inject
    -    protected BlockAsyncRendererExecutor executor;
    -
         @MockComponent
         private DocumentAccessBridge dab;
     
    @@ -100,11 +98,16 @@ class ContextMacroTest
         private DocumentReferenceResolver<String> macroReferenceResolver;
     
         @MockComponent
    -    protected DocumentReferenceResolver<String> resolver;
    +    private DocumentReferenceResolver<String> resolver;
     
         @InjectMockComponents
         private ContextMacro macro;
     
    +    @InjectComponentManager
    +    private MockitoComponentManager componentManager;
    +
    +    private BlockAsyncRendererExecutor executor;
    +
         @BeforeEach
         public void beforeEach() throws Exception
         {
    @@ -117,6 +120,8 @@ public void beforeEach() throws Exception
     
             when(this.macroReferenceResolver.resolve(eq("target"), any())).thenReturn(TARGET_REFERENCE);
             when(this.resolver.resolve("source")).thenReturn(SOURCE_REFERENCE);
    +
    +        this.executor = this.componentManager.getInstance(BlockAsyncRendererExecutor.class);
         }
     
         @Test
    
dd3f4735b419

XWIKI-19856: Bad execution setup on the context macro

https://github.com/xwiki/xwiki-platformThomas MortagneSep 9, 2022via ghsa
1 file changed · +3 3
  • xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-context/src/main/java/org/xwiki/rendering/internal/macro/context/ContextMacro.java+3 3 modified
    @@ -170,14 +170,14 @@ public List<Block> execute(ContextMacroParameters parameters, String content, Ma
             // care of many other things
             BlockAsyncRendererConfiguration configuration = createBlockAsyncRendererConfiguration(null, xdom, context);
     
    -        // Configure the Transformation Context XDOM depending on the mode asked.
    -        configuration.setXDOM(getXDOM(referencedDocReference, parameters));
    -
             Map<String, Object> backupObjects = new HashMap<>();
             try {
                 // Switch the context document
                 this.documentAccessBridge.pushDocumentInContext(backupObjects, referencedDocReference);
     
    +            // Configure the Transformation Context XDOM depending on the mode asked.
    +            configuration.setXDOM(getXDOM(referencedDocReference, parameters));
    +
                 // Execute the content
                 Block result = this.executor.execute(configuration);
     
    
bd34ad6710ed

XWIKI-19856: Macro execution as any user without programming rights through the context macro

https://github.com/xwiki/xwiki-platformThomas MortagneSep 9, 2022via ghsa
9 files changed · +421 300
  • xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-api/src/main/java/org/xwiki/rendering/async/internal/block/BlockAsyncRendererConfiguration.java+31 2 modified
    @@ -31,6 +31,7 @@
     import org.xwiki.model.reference.EntityReference;
     import org.xwiki.rendering.async.internal.AsyncRendererConfiguration;
     import org.xwiki.rendering.block.Block;
    +import org.xwiki.rendering.block.XDOM;
     import org.xwiki.rendering.syntax.Syntax;
     import org.xwiki.rendering.transformation.TransformationContext;
     
    @@ -46,6 +47,8 @@ public class BlockAsyncRendererConfiguration extends AsyncRendererConfiguration
     
         private Block block;
     
    +    private XDOM xdom;
    +
         private boolean asyncAllowed;
     
         private boolean cacheAllowed;
    @@ -70,8 +73,12 @@ public class BlockAsyncRendererConfiguration extends AsyncRendererConfiguration
          */
         public BlockAsyncRendererConfiguration(List<?> idElements, Block block)
         {
    -        this.id = new ArrayList<>(idElements.size());
    -        addElements(idElements);
    +        if (idElements != null) {
    +            this.id = new ArrayList<>(idElements.size());
    +            addElements(idElements);
    +        } else {
    +            this.id = new ArrayList<>();
    +        }
             this.block = block;
     
             // Enabled by default
    @@ -113,6 +120,28 @@ public Block getBlock()
             return this.block;
         }
     
    +    /**
    +     * @return the XDOM to use in the transformation context
    +     * @since 14.8RC1
    +     * @since 14.4.5
    +     * @since 13.10.10
    +     */
    +    public XDOM getXDOM()
    +    {
    +        return this.xdom;
    +    }
    +
    +    /**
    +     * @param xdom the XDOM to use in the transformation context
    +     * @since 14.8RC1
    +     * @since 14.4.5
    +     * @since 13.10.10
    +     */
    +    public void setXDOM(XDOM xdom)
    +    {
    +        this.xdom = xdom;
    +    }
    +
         /**
          * @return true if the execution should be asynchronous if possible
          */
    
  • xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-api/src/main/java/org/xwiki/rendering/async/internal/block/DefaultBlockAsyncRenderer.java+3 5 modified
    @@ -119,11 +119,9 @@ public Block execute(boolean async, boolean cached) throws RenderingException
                     block = PARSERUTILS.convertToInline(block, true);
                 }
     
    -            // Create a XDOM instance for the transformation context
    -            XDOM xdom;
    -            if (block instanceof XDOM) {
    -                xdom = (XDOM) block;
    -            } else {
    +            // Get the XDOM instance for the transformation context
    +            XDOM xdom = this.configuration.getXDOM();
    +            if (xdom == null) {
                     Block rootBlock = block.getRoot();
     
                     if (rootBlock instanceof XDOM) {
    
  • xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/pom.xml+12 20 modified
    @@ -37,7 +37,7 @@
       <dependencies>
         <dependency>
           <groupId>org.xwiki.platform</groupId>
    -      <artifactId>xwiki-platform-rendering-async-default</artifactId>
    +      <artifactId>xwiki-platform-rendering-async-api</artifactId>
           <version>${project.version}</version>
         </dependency>
         <dependency>
    @@ -52,6 +52,12 @@
         </dependency>
     
         <!-- Testing dependencies -->
    +    <dependency>
    +      <groupId>org.xwiki.platform</groupId>
    +      <artifactId>xwiki-platform-rendering-async-default</artifactId>
    +      <version>${project.version}</version>
    +      <scope>test</scope>
    +    </dependency>
         <dependency>
           <groupId>org.xwiki.rendering</groupId>
           <artifactId>xwiki-rendering-syntax-xwiki21</artifactId>
    @@ -81,24 +87,10 @@
           <artifactId>javax.servlet-api</artifactId>
           <scope>test</scope>
         </dependency>
    +    <dependency>
    +      <groupId>org.mortbay.jasper</groupId>
    +      <artifactId>apache-el</artifactId>
    +      <scope>test</scope>
    +    </dependency>
       </dependencies>
    -  <build>
    -    <plugins>
    -      <plugin>
    -        <groupId>org.apache.maven.plugins</groupId>
    -        <artifactId>maven-checkstyle-plugin</artifactId>
    -        <executions>
    -          <execution>
    -            <!-- Specify the "default" execution id so that the "blocker" one is always executed -->
    -            <id>default</id>
    -            <configuration>
    -              <excludes>
    -                org/xwiki/rendering/internal/macro/display/DisplayMacro.java
    -              </excludes>
    -            </configuration>
    -          </execution>
    -        </executions>
    -      </plugin>
    -    </plugins>
    -  </build>
     </project>
    
  • xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/src/main/java/org/xwiki/rendering/async/internal/AbstractExecutedContentMacro.java+147 0 added
    @@ -0,0 +1,147 @@
    +/*
    + * 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.rendering.async.internal;
    +
    +import java.util.List;
    +
    +import javax.inject.Inject;
    +
    +import org.xwiki.bridge.DocumentAccessBridge;
    +import org.xwiki.model.reference.DocumentReference;
    +import org.xwiki.model.reference.DocumentReferenceResolver;
    +import org.xwiki.rendering.async.internal.block.BlockAsyncRendererConfiguration;
    +import org.xwiki.rendering.async.internal.block.BlockAsyncRendererExecutor;
    +import org.xwiki.rendering.block.Block;
    +import org.xwiki.rendering.block.Block.Axes;
    +import org.xwiki.rendering.block.MacroBlock;
    +import org.xwiki.rendering.block.MetaDataBlock;
    +import org.xwiki.rendering.block.match.MetadataBlockMatcher;
    +import org.xwiki.rendering.listener.MetaData;
    +import org.xwiki.rendering.macro.AbstractMacro;
    +import org.xwiki.rendering.macro.Macro;
    +import org.xwiki.rendering.macro.MacroContentParser;
    +import org.xwiki.rendering.macro.descriptor.ContentDescriptor;
    +import org.xwiki.rendering.transformation.MacroTransformationContext;
    +import org.xwiki.rendering.transformation.RenderingContext;
    +
    +/**
    + * Base class to implement a macro which have content to execute.
    + * 
    + * @param <P> the type of the macro parameters bean
    + * @version $Id$
    + * @since 14.8RC1
    + * @since 14.4.5
    + * @since 13.10.10
    + */
    +public abstract class AbstractExecutedContentMacro<P> extends AbstractMacro<P>
    +{
    +    @Inject
    +    protected BlockAsyncRendererExecutor executor;
    +
    +    @Inject
    +    protected MacroContentParser parser;
    +
    +    @Inject
    +    protected DocumentAccessBridge documentAccessBridge;
    +
    +    @Inject
    +    protected DocumentReferenceResolver<String> resolver;
    +
    +    @Inject
    +    protected RenderingContext renderingContext;
    +
    +    /**
    +     * Creates a new {@link Macro} instance.
    +     *
    +     * @param name the name of the macro (eg "Table Of Contents" for the TOC macro)
    +     * @param description string describing this macro.
    +     * @param contentDescriptor the {@link ContentDescriptor} describing the content of this macro.
    +     * @param parametersBeanClass class of the parameters bean.
    +     */
    +    protected AbstractExecutedContentMacro(String name, String description, ContentDescriptor contentDescriptor,
    +        Class<?> parametersBeanClass)
    +    {
    +        super(name, description, contentDescriptor, parametersBeanClass);
    +    }
    +
    +    @Override
    +    public boolean supportsInlineMode()
    +    {
    +        return true;
    +    }
    +
    +    protected String getCurrentSource(MacroTransformationContext context)
    +    {
    +        String currentSource = null;
    +
    +        if (context != null) {
    +            currentSource =
    +                context.getTransformationContext() != null ? context.getTransformationContext().getId() : null;
    +
    +            MacroBlock currentMacroBlock = context.getCurrentMacroBlock();
    +
    +            if (currentMacroBlock != null) {
    +                MetaDataBlock metaDataBlock =
    +                    currentMacroBlock.getFirstBlock(new MetadataBlockMatcher(MetaData.SOURCE), Axes.ANCESTOR_OR_SELF);
    +
    +                if (metaDataBlock != null) {
    +                    currentSource = (String) metaDataBlock.getMetaData().getMetaData(MetaData.SOURCE);
    +                }
    +            }
    +        }
    +
    +        return currentSource;
    +    }
    +
    +    protected BlockAsyncRendererConfiguration createBlockAsyncRendererConfiguration(List<?> idElements, Block content,
    +        MacroTransformationContext context)
    +    {
    +        return createBlockAsyncRendererConfiguration(idElements, content, getCurrentSource(context), context);
    +    }
    +
    +    protected BlockAsyncRendererConfiguration createBlockAsyncRendererConfiguration(List<?> idElements, Block content,
    +        String source, MacroTransformationContext context)
    +    {
    +        BlockAsyncRendererConfiguration configuration = new BlockAsyncRendererConfiguration(idElements, content);
    +
    +        // Set author
    +        if (source != null) {
    +            DocumentReference sourceReference = this.resolver.resolve(source);
    +            configuration.setSecureReference(sourceReference, this.documentAccessBridge.getCurrentAuthorReference());
    +
    +            // Invalidate the cache when the document containing the macro call is modified
    +            configuration.useEntity(sourceReference);
    +        }
    +
    +        // Indicate if the result should be inline or not
    +        configuration.setInline(context.isInline());
    +
    +        // Indicate the syntax of the content
    +        configuration.setDefaultSyntax(this.parser.getCurrentSyntax(context));
    +
    +        // Indicate the target syntax
    +        configuration.setTargetSyntax(this.renderingContext.getTargetSyntax());
    +
    +        // Set the transformation id
    +        configuration.setTransformationId(context.getTransformationContext().getId());
    +
    +        return configuration;
    +    }
    +}
    
  • xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-async/xwiki-platform-rendering-async-macro/src/main/java/org/xwiki/rendering/async/internal/AsyncMacro.java+4 79 modified
    @@ -28,27 +28,16 @@
     import javax.inject.Named;
     import javax.inject.Singleton;
     
    -import org.xwiki.bridge.DocumentAccessBridge;
     import org.xwiki.component.annotation.Component;
    -import org.xwiki.model.reference.DocumentReference;
    -import org.xwiki.model.reference.DocumentReferenceResolver;
     import org.xwiki.rendering.async.AsyncContext;
     import org.xwiki.rendering.async.AsyncMacroParameters;
     import org.xwiki.rendering.async.internal.block.BlockAsyncRendererConfiguration;
    -import org.xwiki.rendering.async.internal.block.BlockAsyncRendererExecutor;
     import org.xwiki.rendering.block.Block;
    -import org.xwiki.rendering.block.Block.Axes;
    -import org.xwiki.rendering.block.MacroBlock;
     import org.xwiki.rendering.block.MetaDataBlock;
     import org.xwiki.rendering.block.XDOM;
    -import org.xwiki.rendering.block.match.MetadataBlockMatcher;
    -import org.xwiki.rendering.listener.MetaData;
    -import org.xwiki.rendering.macro.AbstractMacro;
    -import org.xwiki.rendering.macro.MacroContentParser;
     import org.xwiki.rendering.macro.MacroExecutionException;
     import org.xwiki.rendering.macro.descriptor.DefaultContentDescriptor;
     import org.xwiki.rendering.transformation.MacroTransformationContext;
    -import org.xwiki.rendering.transformation.RenderingContext;
     
     /**
      * Asynchronous and cached execution of wiki content.
    @@ -59,31 +48,16 @@
     @Component
     @Named("async")
     @Singleton
    -public class AsyncMacro extends AbstractMacro<AsyncMacroParameters>
    +public class AsyncMacro extends AbstractExecutedContentMacro<AsyncMacroParameters>
     {
         /**
          * The description of the macro.
          */
         private static final String DESCRIPTION = "Asynchronous and cached execution of wiki content.";
     
    -    @Inject
    -    private BlockAsyncRendererExecutor executor;
    -
    -    @Inject
    -    private MacroContentParser parser;
    -
    -    @Inject
    -    private DocumentAccessBridge documentAccessBridge;
    -
    -    @Inject
    -    private DocumentReferenceResolver<String> resolver;
    -
         @Inject
         private AsyncContext asyncContext;
     
    -    @Inject
    -    private RenderingContext renderingContext;
    -
         /**
          * Default constructor.
          */
    @@ -95,35 +69,6 @@ public AsyncMacro()
             setDefaultCategories(Set.of(DEFAULT_CATEGORY_CONTENT));
         }
     
    -    @Override
    -    public boolean supportsInlineMode()
    -    {
    -        return true;
    -    }
    -
    -    private String getCurrentSource(MacroTransformationContext context)
    -    {
    -        String currentSource = null;
    -
    -        if (context != null) {
    -            currentSource =
    -                context.getTransformationContext() != null ? context.getTransformationContext().getId() : null;
    -
    -            MacroBlock currentMacroBlock = context.getCurrentMacroBlock();
    -
    -            if (currentMacroBlock != null) {
    -                MetaDataBlock metaDataBlock =
    -                    currentMacroBlock.getFirstBlock(new MetadataBlockMatcher(MetaData.SOURCE), Axes.ANCESTOR_OR_SELF);
    -
    -                if (metaDataBlock != null) {
    -                    currentSource = (String) metaDataBlock.getMetaData().getMetaData(MetaData.SOURCE);
    -                }
    -            }
    -        }
    -
    -        return currentSource;
    -    }
    -
         @Override
         public List<Block> execute(AsyncMacroParameters parameters, String content, MacroTransformationContext context)
             throws MacroExecutionException
    @@ -156,19 +101,8 @@ public List<Block> execute(AsyncMacroParameters parameters, String content, Macr
                 }
             }
     
    -        BlockAsyncRendererConfiguration configuration = new BlockAsyncRendererConfiguration(idElements, xdom);
    -
    -        // Set author
    -        if (source != null) {
    -            DocumentReference sourceReference = this.resolver.resolve(source);
    -            configuration.setSecureReference(sourceReference, this.documentAccessBridge.getCurrentAuthorReference());
    -
    -            // Invalidate the cache when the document containing the macro call is modified
    -            configuration.useEntity(sourceReference);
    -        }
    -
    -        // Indicate if the result should be inline or not
    -        configuration.setInline(context.isInline());
    +        BlockAsyncRendererConfiguration configuration =
    +            createBlockAsyncRendererConfiguration(idElements, xdom, source, context);
     
             // Enable/disable async
             configuration.setAsyncAllowed(parameters.isAsync());
    @@ -177,21 +111,12 @@ public List<Block> execute(AsyncMacroParameters parameters, String content, Macr
             // Indicate context entries
             configuration.setContextEntries(parameters.getContext());
     
    -        // Indicate the syntax of the content
    -        configuration.setDefaultSyntax(this.parser.getCurrentSyntax(context));
    -
    -        // Indicate the target syntax
    -        configuration.setTargetSyntax(this.renderingContext.getTargetSyntax());
    -
    -        // Set the transformation id
    -        configuration.setTransformationId(context.getTransformationContext().getId());
    -
             try {
                 Block result = this.executor.execute(configuration);
     
                 // Indicate the content is not transformed if the current execution is not async
                 if (!parameters.isAsync() || !this.asyncContext.isEnabled()) {
    -                result = new MetaDataBlock(Collections.singletonList(result), this.getNonGeneratedContentMetaData());
    +                result = new MetaDataBlock(Collections.singletonList(result), getNonGeneratedContentMetaData());
                 }
     
                 return Collections.singletonList(result);
    
  • xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-context/pom.xml+18 1 modified
    @@ -38,7 +38,7 @@
       <dependencies>
         <dependency>
           <groupId>org.xwiki.platform</groupId>
    -      <artifactId>xwiki-platform-bridge</artifactId>
    +      <artifactId>xwiki-platform-rendering-async-macro</artifactId>
           <version>${project.version}</version>
         </dependency>
         <dependency>
    @@ -47,12 +47,29 @@
           <version>${project.version}</version>
           <scope>runtime</scope>
         </dependency>
    +
         <!-- Test Dependencies -->
    +    <dependency>
    +      <groupId>org.xwiki.platform</groupId>
    +      <artifactId>xwiki-platform-rendering-async-default</artifactId>
    +      <version>${project.version}</version>
    +      <scope>test</scope>
    +    </dependency>
         <dependency>
           <groupId>org.xwiki.rendering</groupId>
           <artifactId>xwiki-rendering-macro-toc</artifactId>
           <version>${rendering.version}</version>
           <scope>test</scope>
         </dependency>
    +    <dependency>
    +      <groupId>javax.servlet</groupId>
    +      <artifactId>javax.servlet-api</artifactId>
    +      <scope>test</scope>
    +    </dependency>
    +    <dependency>
    +      <groupId>org.mortbay.jasper</groupId>
    +      <artifactId>apache-el</artifactId>
    +      <scope>test</scope>
    +    </dependency>
       </dependencies>
     </project>
    
  • xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-context/src/main/java/org/xwiki/rendering/internal/macro/context/ContextMacro.java+83 84 modified
    @@ -20,6 +20,7 @@
     package org.xwiki.rendering.internal.macro.context;
     
     import java.util.Arrays;
    +import java.util.Collections;
     import java.util.HashMap;
     import java.util.List;
     import java.util.Map;
    @@ -29,24 +30,26 @@
     import javax.inject.Named;
     import javax.inject.Singleton;
     
    -import org.xwiki.bridge.DocumentAccessBridge;
     import org.xwiki.bridge.DocumentModelBridge;
     import org.xwiki.component.annotation.Component;
     import org.xwiki.model.reference.DocumentReference;
     import org.xwiki.model.reference.DocumentReferenceResolver;
    +import org.xwiki.rendering.async.internal.AbstractExecutedContentMacro;
    +import org.xwiki.rendering.async.internal.block.BlockAsyncRendererConfiguration;
     import org.xwiki.rendering.block.Block;
     import org.xwiki.rendering.block.MetaDataBlock;
     import org.xwiki.rendering.block.XDOM;
     import org.xwiki.rendering.listener.MetaData;
    -import org.xwiki.rendering.macro.AbstractMacro;
    -import org.xwiki.rendering.macro.MacroContentParser;
     import org.xwiki.rendering.macro.MacroExecutionException;
     import org.xwiki.rendering.macro.context.ContextMacroParameters;
     import org.xwiki.rendering.macro.context.TransformationContextMode;
     import org.xwiki.rendering.macro.descriptor.DefaultContentDescriptor;
     import org.xwiki.rendering.transformation.MacroTransformationContext;
     import org.xwiki.rendering.transformation.TransformationContext;
     import org.xwiki.rendering.transformation.TransformationManager;
    +import org.xwiki.security.authorization.AccessDeniedException;
    +import org.xwiki.security.authorization.AuthorizationManager;
    +import org.xwiki.security.authorization.Right;
     
     /**
      * Execute the macro's content in the context of another document's reference.
    @@ -57,7 +60,7 @@
     @Component
     @Named("context")
     @Singleton
    -public class ContextMacro extends AbstractMacro<ContextMacroParameters>
    +public class ContextMacro extends AbstractExecutedContentMacro<ContextMacroParameters>
     {
         /**
          * The description of the macro.
    @@ -69,27 +72,15 @@ public class ContextMacro extends AbstractMacro<ContextMacroParameters>
          */
         private static final String CONTENT_DESCRIPTION = "The content to execute";
     
    -    /**
    -     * Used to set the current document in the context (old way) and check rights.
    -     */
         @Inject
    -    private DocumentAccessBridge documentAccessBridge;
    +    private AuthorizationManager authorizationManager;
     
    -    /**
    -     * The parser used to parse macro content.
    -     */
         @Inject
    -    private MacroContentParser contentParser;
    +    private TransformationManager transformationManager;
     
    -    /**
    -     * Used to transform document links into absolute references.
    -     */
         @Inject
         @Named("macro")
    -    private DocumentReferenceResolver<String> macroDocumentReferenceResolver;
    -
    -    @Inject
    -    private TransformationManager transformationManager;
    +    private DocumentReferenceResolver<String> macroReferenceResolver;
     
         /**
          * Create and initialize the descriptor of the macro.
    @@ -105,10 +96,48 @@ public ContextMacro()
             setDefaultCategories(Set.of(DEFAULT_CATEGORY_DEVELOPMENT));
         }
     
    -    @Override
    -    public boolean supportsInlineMode()
    +    private void checkAccess(DocumentReference currentAuthor, DocumentReference referencedDocReference)
    +        throws MacroExecutionException
         {
    -        return true;
    +        // Current author must have view right on the target document to use it as context document
    +        try {
    +            this.authorizationManager.checkAccess(Right.VIEW, currentAuthor, referencedDocReference);
    +        } catch (AccessDeniedException e) {
    +            throw new MacroExecutionException("Author [" + currentAuthor
    +                + "] is not allowed to access target document [" + referencedDocReference + "]", e);
    +        }
    +    }
    +
    +    private XDOM getXDOM(DocumentReference referencedDocReference, ContextMacroParameters parameters)
    +        throws MacroExecutionException
    +    {
    +        try {
    +            if (parameters.getTransformationContext() == TransformationContextMode.DOCUMENT
    +                || parameters.getTransformationContext() == TransformationContextMode.TRANSFORMATIONS) {
    +                // Apply the transformations but with a Transformation Context having the XDOM of the passed
    +                // document so that macros execute on the passed document's XDOM (e.g. the TOC macro will generate
    +                // the toc for the passed document instead of the current document).
    +                DocumentModelBridge referencedDoc =
    +                    this.documentAccessBridge.getTranslatedDocumentInstance(referencedDocReference);
    +                XDOM referencedXDOM = referencedDoc.getXDOM();
    +
    +                if (parameters.getTransformationContext() == TransformationContextMode.TRANSFORMATIONS) {
    +                    // Get the XDOM from the referenced doc but with Transformations applied so that all macro are
    +                    // executed and contribute XDOM elements.
    +                    // IMPORTANT: This can be dangerous since it means executing macros, and thus also script macros
    +                    // defined in the referenced document. To be used with caution.
    +                    TransformationContext referencedTxContext =
    +                        new TransformationContext(referencedXDOM, referencedDoc.getSyntax());
    +                    this.transformationManager.performTransformations(referencedXDOM, referencedTxContext);
    +                }
    +
    +                return referencedXDOM;
    +            }
    +        } catch (Exception e) {
    +            throw new MacroExecutionException("Failed to resolve the XDOM to use in the transformation", e);
    +        }
    +
    +        return null;
         }
     
         @Override
    @@ -120,75 +149,45 @@ public List<Block> execute(ContextMacroParameters parameters, String content, Ma
                     + "set in the context as the current document.");
             }
     
    +        DocumentReference currentAuthor = this.documentAccessBridge.getCurrentAuthorReference();
             DocumentReference referencedDocReference =
    -            this.macroDocumentReferenceResolver.resolve(parameters.getDocument(), context.getCurrentMacroBlock());
    +            this.macroReferenceResolver.resolve(parameters.getDocument(), context.getCurrentMacroBlock());
     
    -        boolean currentContextHasProgrammingRights = this.documentAccessBridge.hasProgrammingRights();
    +        // Make sure the author is allowed to use the target document
    +        checkAccess(currentAuthor, referencedDocReference);
     
    -        List<Block> result;
    -        try {
    -            Map<String, Object> backupObjects = new HashMap<>();
    -            try {
    -                this.documentAccessBridge.pushDocumentInContext(backupObjects, referencedDocReference);
    -
    -                // The current document is now the passed document. Check for programming rights for it. If it has
    -                // programming rights then the initial current document also needs programming right, else throw an
    -                // error since it would be a security breach otherwise.
    -                if (this.documentAccessBridge.hasProgrammingRights() && !currentContextHasProgrammingRights) {
    -                    throw new MacroExecutionException("Current document must have programming rights since the "
    -                        + "context document provided [" + parameters.getDocument() + "] has programming rights.");
    -                }
    +        MetaData metadata = new MetaData();
    +        metadata.addMetaData(MetaData.SOURCE, parameters.getDocument());
    +        metadata.addMetaData(MetaData.BASE, parameters.getDocument());
     
    -                MetaData metadata = new MetaData();
    -                metadata.addMetaData(MetaData.SOURCE, parameters.getDocument());
    -                metadata.addMetaData(MetaData.BASE, parameters.getDocument());
    -
    -                XDOM xdom = this.contentParser.parse(content, context, false, metadata, false);
    -
    -                // Configure the  Transformation Context depending on the mode asked.
    -                if (parameters.getTransformationContext() == TransformationContextMode.DOCUMENT
    -                    || parameters.getTransformationContext() == TransformationContextMode.TRANSFORMATIONS)
    -                {
    -                    // Apply the transformations but with a Transformation Context having the XDOM of the passed
    -                    // document so that macros execute on the passed document's XDOM (e.g. the TOC macro will generate
    -                    // the toc for the passed document instead of the current document).
    -                    DocumentModelBridge referencedDoc =
    -                        this.documentAccessBridge.getTranslatedDocumentInstance(referencedDocReference);
    -                    XDOM referencedXDOM = referencedDoc.getXDOM();
    -
    -                    if (parameters.getTransformationContext() == TransformationContextMode.TRANSFORMATIONS) {
    -                        // Get the XDOM from the referenced doc but with Transformations applied so that all macro are
    -                        // executed and contribute XDOM elements.
    -                        // IMPORTANT: This can be dangerous since it means executing macros, and thus also script macros
    -                        // defined in the referenced document. To be used with caution.
    -                        TransformationContext referencedTxContext =
    -                            new TransformationContext(referencedXDOM, referencedDoc.getSyntax());
    -                        this.transformationManager.performTransformations(referencedXDOM, referencedTxContext);
    -                    }
    -
    -                    // Now execute transformation on the context macro content but with the referenced XDOM in the
    -                    // Transformation context!
    -                    TransformationContext txContext =
    -                        new TransformationContext(referencedXDOM, referencedDoc.getSyntax());
    -                    this.transformationManager.performTransformations(xdom, txContext);
    -                }
    +        XDOM xdom = this.parser.parse(content, context, false, metadata, context.isInline());
     
    -                // Keep metadata so that the result stay associated to context properties when inserted in the parent
    -                // XDOM
    -                result = Arrays.asList((Block) new MetaDataBlock(xdom.getChildren(), xdom.getMetaData()));
    +        if (xdom.getChildren().isEmpty()) {
    +            return Collections.emptyList();
    +        }
     
    -            } finally {
    -                this.documentAccessBridge.popDocumentFromContext(backupObjects);
    -            }
    +        // Reuse the very generic async rendering framework (even if we don't do async and caching) since it's taking
    +        // care of many other things
    +        BlockAsyncRendererConfiguration configuration = createBlockAsyncRendererConfiguration(null, xdom, context);
    +
    +        // Configure the Transformation Context XDOM depending on the mode asked.
    +        configuration.setXDOM(getXDOM(referencedDocReference, parameters));
    +
    +        Map<String, Object> backupObjects = new HashMap<>();
    +        try {
    +            // Switch the context document
    +            this.documentAccessBridge.pushDocumentInContext(backupObjects, referencedDocReference);
    +
    +            // Execute the content
    +            Block result = this.executor.execute(configuration);
    +
    +            // Keep metadata so that the result stay associated to context properties when inserted in the parent XDOM
    +            return Arrays.asList((Block) new MetaDataBlock(result.getChildren(), xdom.getMetaData()));
             } catch (Exception e) {
    -            if (e instanceof MacroExecutionException) {
    -                throw (MacroExecutionException) e;
    -            } else {
    -                throw new MacroExecutionException(
    -                    String.format("Failed to render page in the context of [%s]", referencedDocReference), e);
    -            }
    +            throw new MacroExecutionException("Failed start the execution of the macro", e);
    +        } finally {
    +            // Restore the context document
    +            this.documentAccessBridge.popDocumentFromContext(backupObjects);
             }
    -
    -        return result;
         }
     }
    
  • xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-context/src/test/java/org/xwiki/rendering/internal/macro/context/ContextMacroTest.java+92 103 modified
    @@ -22,178 +22,167 @@
     import java.util.Arrays;
     import java.util.Collections;
     
    -import org.junit.Assert;
    -import org.junit.Before;
    -import org.junit.Rule;
    -import org.junit.Test;
    +import javax.inject.Inject;
    +import javax.inject.Named;
    +
    +import org.junit.jupiter.api.BeforeEach;
    +import org.junit.jupiter.api.Test;
    +import org.mockito.ArgumentCaptor;
     import org.xwiki.bridge.DocumentAccessBridge;
     import org.xwiki.bridge.DocumentModelBridge;
     import org.xwiki.model.reference.DocumentReference;
     import org.xwiki.model.reference.DocumentReferenceResolver;
     import org.xwiki.properties.BeanDescriptor;
     import org.xwiki.properties.BeanManager;
    -import org.xwiki.rendering.block.Block;
    -import org.xwiki.rendering.block.LinkBlock;
    +import org.xwiki.rendering.async.internal.block.BlockAsyncRendererConfiguration;
    +import org.xwiki.rendering.async.internal.block.BlockAsyncRendererExecutor;
     import org.xwiki.rendering.block.MacroBlock;
    -import org.xwiki.rendering.block.ParagraphBlock;
    +import org.xwiki.rendering.block.WordBlock;
     import org.xwiki.rendering.block.XDOM;
     import org.xwiki.rendering.listener.MetaData;
    -import org.xwiki.rendering.listener.reference.ResourceReference;
    -import org.xwiki.rendering.listener.reference.ResourceType;
     import org.xwiki.rendering.macro.MacroContentParser;
     import org.xwiki.rendering.macro.MacroExecutionException;
     import org.xwiki.rendering.macro.context.ContextMacroParameters;
     import org.xwiki.rendering.syntax.Syntax;
     import org.xwiki.rendering.transformation.MacroTransformationContext;
    -import org.xwiki.test.mockito.MockitoComponentMockingRule;
    -
    -import static org.junit.Assert.*;
    -import static org.mockito.Mockito.*;
    +import org.xwiki.security.authorization.AccessDeniedException;
    +import org.xwiki.security.authorization.AuthorizationManager;
    +import org.xwiki.security.authorization.Right;
    +import org.xwiki.test.TestEnvironment;
    +import org.xwiki.test.annotation.ComponentList;
    +import org.xwiki.test.junit5.mockito.ComponentTest;
    +import org.xwiki.test.junit5.mockito.InjectMockComponents;
    +import org.xwiki.test.junit5.mockito.MockComponent;
    +
    +import static org.junit.jupiter.api.Assertions.assertEquals;
    +import static org.junit.jupiter.api.Assertions.fail;
    +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.verify;
    +import static org.mockito.Mockito.when;
     
     /**
      * Unit tests for {@link ContextMacro}.
      *
      * @version $Id$
      * @since 8.3RC1
      */
    -public class ContextMacroTest
    +@ComponentTest
    +@ComponentList(TestEnvironment.class)
    +class ContextMacroTest
     {
    -    @Rule
    -    public MockitoComponentMockingRule<ContextMacro> mocker = new MockitoComponentMockingRule<>(ContextMacro.class);
    +    private static final DocumentReference AUTHOR = new DocumentReference("wiki", "XWiki", "author");
    +
    +    private static final DocumentReference TARGET_REFERENCE = new DocumentReference("wiki", "space", "target");
    +
    +    private static final DocumentReference SOURCE_REFERENCE = new DocumentReference("wiki", "space", "source");
    +
    +    @Inject
    +    protected BlockAsyncRendererExecutor executor;
    +
    +    @MockComponent
    +    private DocumentAccessBridge dab;
    +
    +    @MockComponent
    +    private BeanManager beanManager;
    +
    +    @MockComponent
    +    private MacroContentParser parser;
    +
    +    @MockComponent
    +    private AuthorizationManager authorization;
    +
    +    @MockComponent
    +    @Named("macro")
    +    private DocumentReferenceResolver<String> macroReferenceResolver;
    +
    +    @MockComponent
    +    protected DocumentReferenceResolver<String> resolver;
     
    -    @Before
    -    public void setUp() throws Exception
    +    @InjectMockComponents
    +    private ContextMacro macro;
    +
    +    @BeforeEach
    +    public void beforeEach() throws Exception
         {
             // Macro Descriptor set up
    -        BeanManager beanManager = this.mocker.getInstance(BeanManager.class);
             BeanDescriptor descriptor = mock(BeanDescriptor.class);
             when(descriptor.getProperties()).thenReturn(Collections.emptyList());
    -        when(beanManager.getBeanDescriptor(any())).thenReturn(descriptor);
    +        when(this.beanManager.getBeanDescriptor(any())).thenReturn(descriptor);
    +
    +        when(this.dab.getCurrentAuthorReference()).thenReturn(AUTHOR);
    +
    +        when(this.macroReferenceResolver.resolve(eq("target"), any())).thenReturn(TARGET_REFERENCE);
    +        when(this.resolver.resolve("source")).thenReturn(SOURCE_REFERENCE);
         }
     
         @Test
    -    public void executeWhenNoDocumentSpecified() throws Exception
    +    void executeWhenNoDocumentSpecified() throws Exception
         {
             ContextMacroParameters parameters = new ContextMacroParameters();
     
             try {
    -            this.mocker.getComponentUnderTest().execute(parameters, "", new MacroTransformationContext());
    +            this.macro.execute(parameters, "", new MacroTransformationContext());
                 fail("Should have thrown an exception");
             } catch (MacroExecutionException expected) {
    -            Assert.assertEquals("You must specify a 'document' parameter pointing to the document to set in the "
    +            assertEquals("You must specify a 'document' parameter pointing to the document to set in the "
                     + "context as the current document.", expected.getMessage());
             }
         }
     
         @Test
    -    public void executeWithReferencedDocumentHavingProgrammingRightsButNotTheCallingDocument() throws Exception
    +    void executeWithReferencedDocumentNotViewableByTheAuthor() throws Exception
         {
             MacroTransformationContext macroContext = new MacroTransformationContext();
             MacroBlock macroBlock = new MacroBlock("context", Collections.emptyMap(), false);
             macroContext.setCurrentMacroBlock(macroBlock);
     
    -        DocumentReferenceResolver<String> resolver =
    -            this.mocker.getInstance(DocumentReferenceResolver.TYPE_STRING, "macro");
    -        when(resolver.resolve("wiki:space.page", macroBlock)).thenReturn(
    -            new DocumentReference("wiki", "space", "page"));
    -
    -        DocumentAccessBridge dab = this.mocker.getInstance(DocumentAccessBridge.class);
    -        when(dab.hasProgrammingRights()).thenReturn(false).thenReturn(true);
    +        doThrow(AccessDeniedException.class).when(this.authorization).checkAccess(Right.VIEW, AUTHOR, TARGET_REFERENCE);
     
             ContextMacroParameters parameters = new ContextMacroParameters();
    -        parameters.setDocument("wiki:space.page");
    +        parameters.setDocument("target");
     
             try {
    -            this.mocker.getComponentUnderTest().execute(parameters, "", macroContext);
    +            this.macro.execute(parameters, "", macroContext);
                 fail("Should have thrown an exception");
             } catch (MacroExecutionException expected) {
    -            assertEquals("Current document must have programming rights since the context document provided ["
    -                + "wiki:space.page] has programming rights.", expected.getMessage());
    +            assertEquals("Author [wiki:XWiki.author] is not allowed to access target document [wiki:space.target]",
    +                expected.getMessage());
             }
         }
     
         @Test
    -    public void executeWithReferencedDocumentHavingProgrammingRightsAndCallingDocumentToo() throws Exception
    -    {
    -        MacroBlock macroBlock = new MacroBlock("context", Collections.<String, String>emptyMap(), false);
    -        MacroTransformationContext macroContext = new MacroTransformationContext();
    -        macroContext.setSyntax(Syntax.XWIKI_2_0);
    -        macroContext.setCurrentMacroBlock(macroBlock);
    -
    -        DocumentReferenceResolver<String> resolver =
    -            this.mocker.getInstance(DocumentReferenceResolver.TYPE_STRING, "macro");
    -        DocumentReference referencedDocumentReference = new DocumentReference("wiki", "space", "page");
    -        when(resolver.resolve("wiki:space.page", macroBlock)).thenReturn(referencedDocumentReference);
    -
    -        DocumentAccessBridge dab = this.mocker.getInstance(DocumentAccessBridge.class);
    -        when(dab.hasProgrammingRights()).thenReturn(true).thenReturn(true);
    -        DocumentModelBridge dmb = mock(DocumentModelBridge.class);
    -        when(dab.getTranslatedDocumentInstance(referencedDocumentReference)).thenReturn(dmb);
    -
    -        MacroContentParser parser = this.mocker.getInstance(MacroContentParser.class);
    -        when(parser.parse(eq(""), same(macroContext), eq(false), any(MetaData.class), eq(false))).thenReturn(
    -            new XDOM(Collections.emptyList()));
    -
    -        ContextMacroParameters parameters = new ContextMacroParameters();
    -        parameters.setDocument("wiki:space.page");
    -
    -        this.mocker.getComponentUnderTest().execute(parameters, "", macroContext);
    -    }
    -
    -    @Test
    -    public void executeOk() throws Exception
    +    void executeOk() throws Exception
         {
             MacroBlock macroBlock = new MacroBlock("context", Collections.<String, String>emptyMap(), false);
    +        MetaData metadata = new MetaData();
    +        metadata.addMetaData(MetaData.SOURCE, "source");
    +        XDOM xdom = new XDOM(Arrays.asList(macroBlock), metadata);
             MacroTransformationContext macroContext = new MacroTransformationContext();
             macroContext.setSyntax(Syntax.XWIKI_2_0);
             macroContext.setCurrentMacroBlock(macroBlock);
     
    -        DocumentReferenceResolver<String> resolver =
    -            this.mocker.getInstance(DocumentReferenceResolver.TYPE_STRING, "macro");
    -        DocumentReference referencedDocumentReference = new DocumentReference("wiki", "space", "page");
    -        when(resolver.resolve("wiki:space.page", macroBlock)).thenReturn(referencedDocumentReference);
    -
    -        DocumentAccessBridge dab = this.mocker.getInstance(DocumentAccessBridge.class);
             DocumentModelBridge dmb = mock(DocumentModelBridge.class);
    -        when(dab.getTranslatedDocumentInstance(referencedDocumentReference)).thenReturn(dmb);
    +        when(this.dab.getTranslatedDocumentInstance(TARGET_REFERENCE)).thenReturn(dmb);
     
    -        MacroContentParser parser = this.mocker.getInstance(MacroContentParser.class);
    -        XDOM xdom = new XDOM(Arrays.asList((Block) new ParagraphBlock(Arrays.asList((Block) new LinkBlock(
    -            Collections.emptyList(), new ResourceReference("", ResourceType.DOCUMENT), false)))));
    -        when(parser.parse(eq(""), same(macroContext), eq(false), any(MetaData.class), eq(false))).thenReturn(xdom);
    +        when(this.parser.parse(eq(""), same(macroContext), eq(false), any(MetaData.class), eq(false))).thenReturn(xdom);
     
             ContextMacroParameters parameters = new ContextMacroParameters();
    -        parameters.setDocument("wiki:space.page");
    -
    -        // Note: we're not testing the returned value here since this is done in integation tests.
    -        this.mocker.getComponentUnderTest().execute(parameters, "", macroContext);
    -    }
    +        parameters.setDocument("target");
     
    -    @Test
    -    public void executeWithRelativeDocumentReferenceParameter() throws Exception
    -    {
    -        MacroBlock macroBlock = new MacroBlock("context", Collections.<String, String>emptyMap(), false);
    +        when(this.executor.execute(any())).thenReturn(new WordBlock("result"));
     
    -        MacroTransformationContext macroContext = new MacroTransformationContext();
    -        macroContext.setSyntax(Syntax.XWIKI_2_0);
    -        macroContext.setCurrentMacroBlock(macroBlock);
    +        this.macro.execute(parameters, "", macroContext);
     
    -        DocumentReferenceResolver<String> resolver =
    -            this.mocker.getInstance(DocumentReferenceResolver.TYPE_STRING, "macro");
    -        DocumentReference referencedDocumentReference = new DocumentReference("basewiki", "basespace", "page");
    -        when(resolver.resolve("page", macroBlock)).thenReturn(referencedDocumentReference);
    -
    -        DocumentAccessBridge dab = this.mocker.getInstance(DocumentAccessBridge.class);
    -        DocumentModelBridge dmb = mock(DocumentModelBridge.class);
    -        when(dab.getTranslatedDocumentInstance(referencedDocumentReference)).thenReturn(dmb);
    -
    -        MacroContentParser parser = this.mocker.getInstance(MacroContentParser.class);
    -        when(parser.parse(eq(""), same(macroContext), eq(false), any(MetaData.class), eq(false))).thenReturn(
    -            new XDOM(Collections.emptyList()));
    -
    -        ContextMacroParameters parameters = new ContextMacroParameters();
    -        parameters.setDocument("page");
    +        ArgumentCaptor<BlockAsyncRendererConfiguration> configurationCaptor =
    +            ArgumentCaptor.forClass(BlockAsyncRendererConfiguration.class);
    +        verify(this.executor).execute(configurationCaptor.capture());
     
    -        this.mocker.getComponentUnderTest().execute(parameters, "", macroContext);
    +        BlockAsyncRendererConfiguration configuration = configurationCaptor.getValue();
    +        assertEquals(AUTHOR, configuration.getSecureAuthorReference());
    +        assertEquals(SOURCE_REFERENCE, configuration.getSecureDocumentReference());
         }
     }
    
  • xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-context/src/test/java/org/xwiki/rendering/macro/context/IntegrationTests.java+31 6 modified
    @@ -21,20 +21,31 @@
     
     import java.io.StringReader;
     
    -import org.junit.runner.RunWith;
     import org.xwiki.bridge.DocumentAccessBridge;
     import org.xwiki.bridge.DocumentModelBridge;
    +import org.xwiki.component.manager.ComponentManager;
     import org.xwiki.component.util.DefaultParameterizedType;
     import org.xwiki.model.reference.DocumentReference;
     import org.xwiki.model.reference.DocumentReferenceResolver;
    +import org.xwiki.query.QueryManager;
    +import org.xwiki.refactoring.internal.ModelBridge;
    +import org.xwiki.refactoring.internal.ReferenceUpdater;
     import org.xwiki.rendering.block.MacroBlock;
     import org.xwiki.rendering.block.XDOM;
     import org.xwiki.rendering.parser.Parser;
    -import org.xwiki.rendering.test.integration.RenderingTestSuite;
    +import org.xwiki.rendering.test.integration.junit5.RenderingTests;
    +import org.xwiki.security.authorization.AuthorizationManager;
    +import org.xwiki.security.authorization.ContextualAuthorizationManager;
    +import org.xwiki.template.TemplateManager;
    +import org.xwiki.test.TestEnvironment;
     import org.xwiki.test.annotation.AllComponents;
    +import org.xwiki.test.annotation.ComponentList;
     import org.xwiki.test.mockito.MockitoComponentManager;
     
    -import static org.mockito.Mockito.*;
    +import static org.mockito.ArgumentMatchers.any;
    +import static org.mockito.ArgumentMatchers.eq;
    +import static org.mockito.Mockito.mock;
    +import static org.mockito.Mockito.when;
     
     /**
      * Run all tests found in {@code *.test} files located in the classpath. These {@code *.test} files must follow the
    @@ -43,15 +54,26 @@
      * @version $Id$
      * @since 8.3RC1
      */
    -@RunWith(RenderingTestSuite.class)
     @AllComponents
    -public class IntegrationTests
    +@ComponentList(TestEnvironment.class)
    +public class IntegrationTests implements RenderingTests
     {
    -    @RenderingTestSuite.Initialized
    +    @RenderingTests.Initialized
         public void initialize(MockitoComponentManager componentManager) throws Exception
         {
    +        // Replace the environment by a test compatible one
    +        componentManager.registerComponent(TestEnvironment.class);
    +        
             // For performance reasons we mock some components to avoid having to draw all oldcore components
     
    +        // Some components we don't really use and which trigger a lot of dependencies
    +        componentManager.registerMockComponent(TemplateManager.class);
    +        componentManager.registerMockComponent(ModelBridge.class);
    +        componentManager.registerMockComponent(QueryManager.class);
    +        componentManager.registerMockComponent(ReferenceUpdater.class);
    +        componentManager.registerMockComponent(AuthorizationManager.class);
    +        componentManager.registerMockComponent(ContextualAuthorizationManager.class);
    +
             // Macro Reference Resolver
             DocumentReferenceResolver<String> macroResolver = componentManager.registerMockComponent(
                 new DefaultParameterizedType(null, DocumentReferenceResolver.class, String.class), "macro");
    @@ -67,5 +89,8 @@ public void initialize(MockitoComponentManager componentManager) throws Exceptio
             Parser parser = componentManager.getInstance(Parser.class, "xwiki/2.1");
             XDOM xdom = parser.parse(new StringReader("= heading1 =\n==heading2=="));
             when(dmb.getXDOM()).thenReturn(xdom);
    +
    +        // Replace the context component manager
    +        componentManager.registerComponent(ComponentManager.class, "context", componentManager);
         }
     }
    

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

7

News mentions

0

No linked articles in our index yet.