CVE-2023-26056 (published 2023-03-02T19:15Z)

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.

CVSS v3 base score: 5.4, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N)

Weakness information:
cwe_id: CWE-863
cwe_name: Incorrect Authorization
description: The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check. This allows attackers to bypass intended access restrictions.
extended_description: 
            Assuming a user with a given identity, authorization is the process of determining whether that user can access a given resource, based on the user's privileges and any permissions or other access-control specifications that apply to the resource.
            When access control checks are incorrectly applied, users are able to access data or perform actions that they should not be allowed to perform. This can lead to a wide range of problems, including information exposures, denial of service, and arbitrary code execution.
         
         

Fix information:
repo_url: https://github.com/xwiki/xwiki-platform
commit_details: repo_url: https://github.com/xwiki/xwiki-platform
author: Thomas Mortagne
author_date: 2022-09-09 14:57:55+02:00
msg: XWIKI-19856: Bad execution setup on the context macro
* 13.10.x compatible test
repository: repo_url: https://github.com/xwiki/xwiki-platform
repo_name: xwiki/xwiki-platform
description: The XWiki platform
repo_language: Java
owner: xwiki
file_changes: filename: ContextMacro.java
change_type: ModificationType.MODIFY
diff: @@ -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 {

programming_language: Java
filename: ContextMacroTest.java
change_type: ModificationType.MODIFY
diff: @@ -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 @@
 
     private static final DocumentReference SOURCE_REFERENCE = new DocumentReference("wiki", "space", "source");
 
-    @Inject
-    protected BlockAsyncRendererExecutor executor;
-
     @MockComponent
     private DocumentAccessBridge dab;
 
@@ -100,11 +98,16 @@
     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

programming_language: Java
repo_url: https://github.com/xwiki/xwiki-platform
commit_details: repo_url: https://github.com/xwiki/xwiki-platform
author: Thomas Mortagne
author_date: 2022-09-09 10:48:51+02:00
msg: XWIKI-19856: Macro execution as any user without programming rights through the context macro
repository: repo_url: https://github.com/xwiki/xwiki-platform
repo_name: xwiki/xwiki-platform
description: The XWiki platform
repo_language: Java
owner: xwiki
file_changes: filename: BlockAsyncRendererConfiguration.java
change_type: ModificationType.MODIFY
diff: @@ -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
      */

programming_language: Java
filename: DefaultBlockAsyncRenderer.java
change_type: ModificationType.MODIFY
diff: @@ -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) {

programming_language: Java
filename: pom.xml
change_type: ModificationType.MODIFY
diff: @@ -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>

programming_language: HTML
filename: AbstractExecutedContentMacro.java
change_type: ModificationType.ADD
diff: @@ -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;
+    }
+}

programming_language: Java
filename: AsyncMacro.java
change_type: ModificationType.MODIFY
diff: @@ -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);

programming_language: Java
filename: pom.xml
change_type: ModificationType.MODIFY
diff: @@ -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>

programming_language: HTML
filename: ContextMacro.java
change_type: ModificationType.MODIFY
diff: @@ -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,17 +30,16 @@
 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;
@@ -47,6 +47,9 @@
 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;
     }
 }

programming_language: Java
filename: ContextMacroTest.java
change_type: ModificationType.MODIFY
diff: @@ -22,33 +22,47 @@
 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}.
@@ -56,144 +70,119 @@
  * @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());
     }
 }

programming_language: Java
filename: IntegrationTests.java
change_type: ModificationType.MODIFY
diff: @@ -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);
     }
 }

programming_language: Java
repo_url: https://github.com/xwiki/xwiki-platform
commit_details: repo_url: https://github.com/xwiki/xwiki-platform
author: Thomas Mortagne
author_date: 2022-09-09 13:41:29+02:00
msg: XWIKI-19856: Bad execution setup on the context macro
repository: repo_url: https://github.com/xwiki/xwiki-platform
repo_name: xwiki/xwiki-platform
description: The XWiki platform
repo_language: Java
owner: xwiki
file_changes: filename: ContextMacro.java
change_type: ModificationType.MODIFY
diff: @@ -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);
 

programming_language: Java