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

XWiki allows privilege escalation through link refactoring

CVE-2025-49580

Description

XWiki is a generic wiki platform. From 8.2 and 7.4.5 until 17.1.0-rc-1, 16.10.4, and 16.4.7, pages can gain script or programming rights when they contain a link and the target of the link is renamed or moved. This might lead to execution of scripts contained in xobjects that should have never been executed. This vulnerability is fixed in 17.1.0-rc-1, 16.10.4, and 16.4.7.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.xwiki.platform:xwiki-platform-refactoring-defaultMaven
>= 17.0.0-rc-1, < 17.1.0-rc-117.1.0-rc-1
org.xwiki.platform:xwiki-platform-refactoring-defaultMaven
>= 16.5.0-rc-1, < 16.10.416.10.4
org.xwiki.platform:xwiki-platform-refactoring-defaultMaven
>= 8.2, < 16.4.716.4.7
org.xwiki.platform:xwiki-platform-refactoring-defaultMaven
>= 7.4.5, < 16.4.716.4.7

Affected products

1

Patches

1
ab209acd780d

XWIKI-22838: Save refactoring link with minor version only

https://github.com/xwiki/xwiki-platformSimon UrliJan 30, 2025via ghsa
4 files changed · +152 29
  • xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/RenamePageIT.java+64 0 modified
    @@ -743,4 +743,68 @@ void renameLinkContainingWiki(TestUtils testUtils, TestReference testReference,
             WikiEditPage wikiEditPage = WikiEditPage.gotoPage(testReference);
             assertEquals("[[MyPage>>xwiki:TestLinkWithWikiNew.WebHome]]", wikiEditPage.getContent());
         }
    +
    +    @Order(11)
    +    @Test
    +    void renameLinkInXObject(TestUtils testUtils, TestReference testReference, TestConfiguration testConfiguration)
    +        throws Exception
    +    {
    +        String userLogin = "RenamePageUser";
    +        String userPwd = "renamepageuser";
    +        testUtils.createUserAndLogin(userLogin, userPwd);
    +        testUtils.loginAsSuperAdmin();
    +        testUtils.createPage(testReference, "Space test");
    +        SpaceReference testSpaceReference = testReference.getLastSpaceReference();
    +        testUtils.setRightsOnSpace(testSpaceReference, "", userLogin, "edit", true);
    +
    +        DocumentReference p1 = new DocumentReference("P1", testSpaceReference);
    +        String p1Reference = testUtils.serializeReference(p1);
    +        testUtils.rest().savePage(p1, "Content P1", "Title P1");
    +
    +        DocumentReference p2 = new DocumentReference("P2", testSpaceReference);
    +        String p2Reference = testUtils.serializeReference(p2);
    +        testUtils.createPage(p2, "Some P2 content", "titleP2");
    +
    +        DocumentReference p3 = new DocumentReference("P3", testSpaceReference);
    +        String script = String.format("{{velocity}}\n"
    +            + "#set ($p2Doc = $xwiki.getDocument('%s'))\n"
    +            + "#set ($authors = $p2Doc.authors)\n"
    +            + "Effective metadata author: $services.user.serialize($authors.effectiveMetadataAuthor)\n"
    +            + "Original metadata author: $services.user.serialize($authors.originalMetadataAuthor)\n"
    +            + "Content author: $services.user.serialize($authors.contentAuthor)\n"
    +            + "{{/velocity}}", p2Reference);
    +
    +        String displayedContent = "Effective metadata author: %1$s\n"
    +            + "Original metadata author: %2$s\n"
    +            + "Content author: %3$s";
    +
    +        testUtils.createPage(p3, script, "titleP3");
    +        String p3Content = testUtils.gotoPage(p3).getContent();
    +
    +        assertEquals(String.format(displayedContent, "XWiki.superadmin", "XWiki.superadmin", "XWiki.superadmin"),
    +            p3Content);
    +
    +        testUtils.login(userLogin, userPwd);
    +        testUtils.rest().savePage(p2, String.format("[[P1 link>>doc:%s]]", p1Reference), "titleP2");
    +        p3Content = testUtils.gotoPage(p3).getContent();
    +        assertEquals(String.format(displayedContent, "xwiki:XWiki." + userLogin, "xwiki:XWiki." + userLogin,
    +                "xwiki:XWiki." + userLogin),
    +            p3Content);
    +
    +        testUtils.loginAsSuperAdmin();
    +        new SolrTestUtils(testUtils, testConfiguration.getServletEngine()).waitEmptyQueue();
    +        RenamePage renamePage = testUtils.gotoPage(p1).rename();
    +        renamePage.getDocumentPicker().setName("P43");
    +        CopyOrRenameOrDeleteStatusPage statusPage = renamePage.clickRenameButton().waitUntilFinished();
    +        assertEquals("Done.", statusPage.getInfoMessage());
    +
    +        testUtils.gotoPage(p2, "edit", "editor=wiki");
    +        WikiEditPage wikiEditPage = new WikiEditPage();
    +        assertEquals(String.format("[[P1 link>>doc:%s]]", p1Reference.replace("P1", "P43")), wikiEditPage.getContent());
    +
    +        p3Content = testUtils.gotoPage(p3).getContent();
    +        assertEquals(String.format(displayedContent, "xwiki:XWiki." + userLogin, "XWiki.superadmin",
    +                "xwiki:XWiki." + userLogin),
    +            p3Content);
    +    }
     }
    
  • xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/DefaultReferenceUpdater.java+18 7 modified
    @@ -36,6 +36,7 @@
     import org.xwiki.job.Job;
     import org.xwiki.job.JobContext;
     import org.xwiki.job.event.status.JobProgressManager;
    +import org.xwiki.localization.LocalizationManager;
     import org.xwiki.model.EntityType;
     import org.xwiki.model.reference.AttachmentReference;
     import org.xwiki.model.reference.DocumentReference;
    @@ -46,6 +47,8 @@
     import org.xwiki.rendering.renderer.BlockRenderer;
     import org.xwiki.rendering.renderer.printer.DefaultWikiPrinter;
     import org.xwiki.rendering.renderer.printer.WikiPrinter;
    +import org.xwiki.user.CurrentUserReference;
    +import org.xwiki.user.UserReferenceResolver;
     
     import com.xpn.xwiki.XWikiContext;
     import com.xpn.xwiki.XWikiException;
    @@ -94,6 +97,12 @@ public class DefaultReferenceUpdater implements ReferenceUpdater
         @Named("context")
         private Provider<ComponentManager> contextComponentManagerProvider;
     
    +    @Inject
    +    private UserReferenceResolver<CurrentUserReference> userReferenceResolver;
    +
    +    @Inject
    +    private LocalizationManager localizationManager;
    +
         @FunctionalInterface
         private interface RenameLambda
         {
    @@ -126,20 +135,22 @@ private String renderXDOM(XDOM content, BlockRenderer renderer)
          * clear whether the content author deserves to be updated or not (even without the side effects).
          * 
          * @param document the document to be saved
    -     * @param comment the revision comment
    -     * @param minorEdit whether it's a minor edit or not
    +     * @param commentTranslationKey the revision comment translation key
          * @throws XWikiException if saving the document fails
          */
    -    private void saveDocumentPreservingContentAuthor(XWikiDocument document, String comment, boolean minorEdit)
    +    private void saveDocumentPreservingAuthors(XWikiDocument document, String commentTranslationKey)
             throws XWikiException
         {
             XWikiContext xcontext = this.xcontextProvider.get();
             // Preserve the content author.
             document.setContentDirty(false);
             // Make sure the version is incremented.
             document.setMetaDataDirty(true);
    -        document.setAuthorReference(xcontext.getUserReference());
    -        xcontext.getWiki().saveDocument(document, comment, minorEdit, xcontext);
    +        document.getAuthors().setOriginalMetadataAuthor(
    +            this.userReferenceResolver.resolve(CurrentUserReference.INSTANCE));
    +        Locale defaultLocale = this.localizationManager.getDefaultLocale();
    +        String comment = this.localizationManager.getTranslationPlain(commentTranslationKey, defaultLocale);
    +        xcontext.getWiki().saveDocument(document, comment, true, xcontext);
         }
     
         private boolean renameLinks(XWikiDocument document, boolean relative, RenameLambda renameLambda)
    @@ -247,11 +258,11 @@ private void renameLinks(XWikiDocument document, EntityReference oldTarget, Enti
     
             if (modified) {
                 if (relative) {
    -                saveDocumentPreservingContentAuthor(document, "Updated the relative links.", true);
    +                saveDocumentPreservingAuthors(document, "refactoring.referenceUpdater.saveMessage.relativeLink");
     
                     info("Updated the relative links from [{}].", currentDocumentReference);
                 } else {
    -                saveDocumentPreservingContentAuthor(document, "Renamed back-links.", false);
    +                saveDocumentPreservingAuthors(document, "refactoring.referenceUpdater.saveMessage.backlinks");
     
                     info("The links from [{}] that were targeting [{}] have been updated to target [{}].",
                         document.getDocumentReferenceWithLocale(), oldTarget, newTarget);
    
  • xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/resources/ApplicationResources.properties+3 0 modified
    @@ -81,3 +81,6 @@ job.question.XClassBreakingQuestion.refactoring/move.tree.title=Pages to move
     
     job.question.XClassBreakingQuestion.refactoring/move.forbiddenTitle=You cannot proceed on this move.
     job.question.XClassBreakingQuestion.refactoring/move.forbiddenExplanation=The pages you selected contain structured data types. Moving these pages might prevent the wiki from working properly. Ask an advanced user to proceed on this refactoring.
    +
    +refactoring.referenceUpdater.saveMessage.relativeLink=Updated the relative links.
    +refactoring.referenceUpdater.saveMessage.backlinks=Renamed back-links.
    \ No newline at end of file
    
  • xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/DefaultReferenceUpdaterTest.java+67 22 modified
    @@ -38,7 +38,9 @@
     import org.xwiki.job.JobContext;
     import org.xwiki.job.Request;
     import org.xwiki.job.event.status.JobProgressManager;
    +import org.xwiki.localization.LocalizationManager;
     import org.xwiki.model.EntityType;
    +import org.xwiki.model.document.DocumentAuthors;
     import org.xwiki.model.reference.AttachmentReference;
     import org.xwiki.model.reference.DocumentReference;
     import org.xwiki.model.reference.DocumentReferenceResolver;
    @@ -75,6 +77,9 @@
     import org.xwiki.test.junit5.mockito.InjectMockComponents;
     import org.xwiki.test.junit5.mockito.MockComponent;
     import org.xwiki.test.mockito.MockitoComponentManager;
    +import org.xwiki.user.CurrentUserReference;
    +import org.xwiki.user.UserReference;
    +import org.xwiki.user.UserReferenceResolver;
     
     import com.xpn.xwiki.XWiki;
     import com.xpn.xwiki.XWikiContext;
    @@ -111,6 +116,12 @@
     // @formatter:on
     class DefaultReferenceUpdaterTest
     {
    +    private static final String SAVE_COMMENT_RELATIVE_LINK_KEY =
    +        "refactoring.referenceUpdater.saveMessage.relativeLink";
    +    private static final String SAVE_COMMENT_BACKLINK_KEY = "refactoring.referenceUpdater.saveMessage.backlinks";
    +    private static final String TRANSLATED_RELATIVE_COMMENT = "Relative link save";
    +    private static final String TRANSLATED_BACKLINK_COMMENT = "Back-link save";
    +
         @MockComponent
         @Named("compact")
         private EntityReferenceSerializer<String> compactEntityReferenceSerializer;
    @@ -169,6 +180,12 @@ class DefaultReferenceUpdaterTest
         @MockComponent
         private JobProgressManager progressManager;
     
    +    @MockComponent
    +    private UserReferenceResolver<CurrentUserReference> userReferenceResolver;
    +
    +    @MockComponent
    +    private LocalizationManager localizationManager;
    +
         @InjectMockComponents
         private DefaultReferenceUpdater updater;
     
    @@ -178,6 +195,9 @@ class DefaultReferenceUpdaterTest
         @Mock
         private XWikiContext xcontext;
     
    +    @Mock
    +    private UserReference currentUserReference;
    +
         private MutableRenderingContext mutableRenderingContext;
     
         int logIndex = 0;
    @@ -203,6 +223,12 @@ void beforeEach() throws Exception
             when(this.jobContext.getCurrentJob()).thenReturn(this.job);
             when(this.job.getRequest()).thenReturn(jobrequest);
             when(this.jobrequest.isVerbose()).thenReturn(true);
    +        when(this.localizationManager.getDefaultLocale()).thenReturn(Locale.FRENCH);
    +        when(this.localizationManager.getTranslationPlain(SAVE_COMMENT_RELATIVE_LINK_KEY, Locale.FRENCH))
    +            .thenReturn(TRANSLATED_RELATIVE_COMMENT);
    +        when(this.localizationManager.getTranslationPlain(SAVE_COMMENT_BACKLINK_KEY, Locale.FRENCH))
    +            .thenReturn(TRANSLATED_BACKLINK_COMMENT);
    +        when(this.userReferenceResolver.resolve(CurrentUserReference.INSTANCE)).thenReturn(currentUserReference);
         }
     
         private void setTextarea(XWikiDocument document, XDOM xdom)
    @@ -242,6 +268,8 @@ void updateRelativeLinks() throws Exception
                 new DocumentReference("wiki", "Main", "WebHome"));
     
             XWikiDocument newDocument = mock(XWikiDocument.class);
    +        DocumentAuthors authors = mock(DocumentAuthors.class);
    +        when(newDocument.getAuthors()).thenReturn(authors);
             when(this.xcontext.getWiki().getDocument(newReference, this.xcontext)).thenReturn(newDocument);
             when(newDocument.getDocumentReference()).thenReturn(newReference);
             when(newDocument.getSyntax()).thenReturn(Syntax.XWIKI_2_1);
    @@ -354,7 +382,7 @@ void updateRelativeLinks() throws Exception
             // Image link relative to the document stay the same
             assertEquals("attachment.txt", xobjectImageBlock.getReference().getReference());
     
    -        verifyDocumentSave(newDocument, "Updated the relative links.", true, true);
    +        verifyDocumentSave(newDocument, true);
         }
     
         @Test
    @@ -364,6 +392,8 @@ void updateRelativeLinksAcrossWikis() throws Exception
             DocumentReference newReference = new DocumentReference("wiki2", "X", "Y");
     
             XWikiDocument newDocument = mock(XWikiDocument.class);
    +        DocumentAuthors authors = mock(DocumentAuthors.class);
    +        when(newDocument.getAuthors()).thenReturn(authors);
             when(this.xcontext.getWiki().getDocument(newReference, this.xcontext)).thenReturn(newDocument);
             when(newDocument.getDocumentReference()).thenReturn(newReference);
             when(newDocument.getSyntax()).thenReturn(Syntax.XWIKI_2_1);
    @@ -418,14 +448,16 @@ void updateRelativeLinksAcrossWikis() throws Exception
             // Space link is also updated, since they were referring entities on a different wiki.
             assertEquals("wiki1:Z", spaceLinkBlock.getReference().getReference());
             assertEquals(ResourceType.SPACE, spaceLinkBlock.getReference().getType());
    -        verifyDocumentSave(newDocument, "Updated the relative links.", true, true);
    +        verifyDocumentSave(newDocument, true);
         }
     
         @Test
         void update() throws Exception
         {
             DocumentReference documentReference = new DocumentReference("wiki", "Space", "Page");
             XWikiDocument document = mock(XWikiDocument.class);
    +        DocumentAuthors authors = mock(DocumentAuthors.class);
    +        when(document.getAuthors()).thenReturn(authors);
             when(this.xcontext.getWiki().getDocument(documentReference, this.xcontext)).thenReturn(document);
             when(document.getDocumentReference()).thenReturn(documentReference);
             when(document.getSyntax()).thenReturn(Syntax.XWIKI_2_1);
    @@ -481,14 +513,16 @@ void update() throws Exception
             assertEquals("xwiki:X.Y.WebHome", absoluteLinkBlock.getReference().getReference());
             assertEquals("X.Y", xobjectLinkBlock.getReference().getReference());
             assertEquals(ResourceType.DOCUMENT, linkBlock.getReference().getType());
    -        verifyDocumentSave(document, "Renamed back-links.", false, false);
    +        verifyDocumentSave(document, false);
         }
     
         @Test
         void renameImage() throws Exception
         {
             DocumentReference documentReference = new DocumentReference("wiki", "Space", "Page");
             XWikiDocument document = mock(XWikiDocument.class);
    +        DocumentAuthors authors = mock(DocumentAuthors.class);
    +        when(document.getAuthors()).thenReturn(authors);
             when(this.xcontext.getWiki().getDocument(documentReference, this.xcontext)).thenReturn(document);
             when(document.getDocumentReference()).thenReturn(documentReference);
             when(document.getSyntax()).thenReturn(Syntax.XWIKI_2_1);
    @@ -523,14 +557,16 @@ void renameImage() throws Exception
     
             assertEquals("X.Y@attachment.txt", imageBlock.getReference().getReference());
             assertEquals(ResourceType.ATTACHMENT, imageBlock.getReference().getType());
    -        verifyDocumentSave(document, "Renamed back-links.", false, false);
    +        verifyDocumentSave(document, false);
         }
     
         @Test
         void renameAttachment() throws Exception
         {
             DocumentReference documentReference = new DocumentReference("wiki", "Space", "Page");
             XWikiDocument document = mock(XWikiDocument.class);
    +        DocumentAuthors authors = mock(DocumentAuthors.class);
    +        when(document.getAuthors()).thenReturn(authors);
             when(this.xcontext.getWiki().getDocument(documentReference, this.xcontext)).thenReturn(document);
             when(document.getDocumentReference()).thenReturn(documentReference);
             when(document.getSyntax()).thenReturn(Syntax.XWIKI_2_1);
    @@ -565,14 +601,16 @@ void renameAttachment() throws Exception
     
             assertEquals("X.Y@attachment.txt", linkBlock.getReference().getReference());
             assertEquals(ResourceType.ATTACHMENT, linkBlock.getReference().getType());
    -        verifyDocumentSave(document, "Renamed back-links.", false, false);
    +        verifyDocumentSave(document, false);
         }
     
         @Test
         void renameNonTerminalDocumentLinks() throws Exception
         {
             DocumentReference documentReference = new DocumentReference("wiki", "Space", "Page");
             XWikiDocument document = mock(XWikiDocument.class);
    +        DocumentAuthors authors = mock(DocumentAuthors.class);
    +        when(document.getAuthors()).thenReturn(authors);
             when(this.xcontext.getWiki().getDocument(documentReference, this.xcontext)).thenReturn(document);
             when(document.getDocumentReference()).thenReturn(documentReference);
             when(document.getSyntax()).thenReturn(Syntax.XWIKI_2_1);
    @@ -623,14 +661,16 @@ void renameNonTerminalDocumentLinks() throws Exception
             assertEquals(ResourceType.DOCUMENT, documentLinkBlock.getReference().getType());
             assertEquals("X", spaceLinkBlock.getReference().getReference());
             assertEquals(ResourceType.SPACE, spaceLinkBlock.getReference().getType());
    -        verifyDocumentSave(document, "Renamed back-links.", false, false);
    +        verifyDocumentSave(document, false);
         }
     
         @Test
         void renameNonTerminalToTerminalDocumentLinks() throws Exception
         {
             DocumentReference documentReference = new DocumentReference("wiki", "Space", "Page");
             XWikiDocument document = mock(XWikiDocument.class);
    +        DocumentAuthors authors = mock(DocumentAuthors.class);
    +        when(document.getAuthors()).thenReturn(authors);
             when(this.xcontext.getWiki().getDocument(documentReference, this.xcontext)).thenReturn(document);
             when(document.getDocumentReference()).thenReturn(documentReference);
             when(document.getSyntax()).thenReturn(Syntax.XWIKI_2_1);
    @@ -685,14 +725,16 @@ void renameNonTerminalToTerminalDocumentLinks() throws Exception
             assertEquals(ResourceType.DOCUMENT, documentLinkBlock.getReference().getType());
             assertEquals("X.Y", spaceLinkBlock.getReference().getReference());
             assertEquals(ResourceType.DOCUMENT, spaceLinkBlock.getReference().getType());
    -        verifyDocumentSave(document, "Renamed back-links.", false, false);
    +        verifyDocumentSave(document, false);
         }
     
         @Test
         void updateFromMacros(MockitoComponentManager componentManager) throws Exception
         {
             DocumentReference documentReference = new DocumentReference("wiki", "Space", "Page");
             XWikiDocument document = mock(XWikiDocument.class);
    +        DocumentAuthors authors = mock(DocumentAuthors.class);
    +        when(document.getAuthors()).thenReturn(authors);
             when(this.xcontext.getWiki().getDocument(documentReference, this.xcontext)).thenReturn(document);
             when(document.getDocumentReference()).thenReturn(documentReference);
             when(document.getSyntax()).thenReturn(Syntax.XWIKI_2_1);
    @@ -750,7 +792,7 @@ void updateFromMacros(MockitoComponentManager componentManager) throws Exception
             verify(this.mutableRenderingContext, times(3)).push(any(), any(), eq(Syntax.XWIKI_2_1), any(), anyBoolean(),
                 any());
             verify(this.mutableRenderingContext, times(3)).pop();
    -        verifyDocumentSave(document, "Renamed back-links.", false, false);
    +        verifyDocumentSave(document, false);
         }
     
         @Test
    @@ -765,6 +807,8 @@ void updateAttachments() throws Exception
             LinkBlock documentLinkBlock = new LinkBlock(List.of(), resourceReference, false);
     
             XWikiDocument document = mock(XWikiDocument.class);
    +        DocumentAuthors authors = mock(DocumentAuthors.class);
    +        when(document.getAuthors()).thenReturn(authors);
             XDOM xdom = mock(XDOM.class);
     
             when(this.xcontext.getWiki().getDocument(documentReference, this.xcontext)).thenReturn(document);
    @@ -783,23 +827,16 @@ void updateAttachments() throws Exception
             updater.update(documentReference, oldLinkTarget, newLinkTarget);
     
             verify(this.progressManager).pushLevelProgress(1, updater);
    -        verify(document).setContent(xdom);
    -        verify(document).setContentDirty(false);
    -        verify(document).setMetaDataDirty(true);
    -        verify(this.xcontext.getWiki()).saveDocument(document, "Renamed back-links.", false, this.xcontext);
    -        verify(this.progressManager).popLevelProgress(updater);
    -        assertEquals(1, this.logCapture.size());
    -        assertEquals(
    -            "The links from [null] that were targeting [Attachment wiki:Space.Source@oldname.txt] have "
    -                + "been updated to target [Attachment wiki:Space.Target@newname.txt].", this.logCapture.getMessage(0));
    -        assertEquals(Level.INFO, this.logCapture.getLogEvent(0).getLevel());
    +        verifyDocumentSave(document, false);
         }
     
         @Test
         void updateFromLinksAndMacros(MockitoComponentManager componentManager) throws Exception
         {
             DocumentReference documentReference = new DocumentReference("wiki", "Space", "Page");
             XWikiDocument document = mock(XWikiDocument.class);
    +        DocumentAuthors authors = mock(DocumentAuthors.class);
    +        when(document.getAuthors()).thenReturn(authors);
             when(this.xcontext.getWiki().getDocument(documentReference, this.xcontext)).thenReturn(document);
             when(document.getDocumentReference()).thenReturn(documentReference);
             when(document.getSyntax()).thenReturn(Syntax.XWIKI_2_1);
    @@ -840,17 +877,19 @@ void updateFromLinksAndMacros(MockitoComponentManager componentManager) throws E
                 newLinkTarget, false, Map.of(oldLinkTarget, newLinkTarget));
             assertEquals("X.Y", documentLinkBlock.getReference().getReference());
             assertEquals(ResourceType.DOCUMENT, documentLinkBlock.getReference().getType());
    -        verifyDocumentSave(document, "Renamed back-links.", false, false);
    +        verifyDocumentSave(document, false);
         }
     
    -    private void verifyDocumentSave(XWikiDocument document, String comment, boolean minorEdit, boolean relative)
    +    private void verifyDocumentSave(XWikiDocument document, boolean relative)
             throws Exception
         {
             // Verify we preserve the content author.
             verify(document).setContentDirty(false);
             // Verify the version is going to be incremented.
             verify(document).setMetaDataDirty(true);
    -        verify(this.xcontext.getWiki()).saveDocument(document, comment, minorEdit, this.xcontext);
    +        String comment = (relative) ? TRANSLATED_RELATIVE_COMMENT : TRANSLATED_BACKLINK_COMMENT;
    +        verify(this.xcontext.getWiki()).saveDocument(document, comment, true, this.xcontext);
    +        verify(document.getAuthors()).setOriginalMetadataAuthor(currentUserReference);
             ILoggingEvent logEvent = this.logCapture.getLogEvent(this.logIndex++);
             if (relative) {
                 assertEquals("Updated the relative links from [{}].", logEvent.getMessage());
    @@ -866,17 +905,23 @@ void updateAndTranslations() throws Exception
         {
             DocumentReference baseDocumentReference = new DocumentReference("wiki", "Space", "Page");
             XWikiDocument baseDocument = mock(XWikiDocument.class);
    +        DocumentAuthors baseAuthors = mock(DocumentAuthors.class);
    +        when(baseDocument.getAuthors()).thenReturn(baseAuthors);
             when(this.xcontext.getWiki().getDocument(baseDocumentReference, this.xcontext)).thenReturn(baseDocument);
             when(baseDocument.getDocumentReference()).thenReturn(baseDocumentReference);
     
             when(baseDocument.getTranslationLocales(xcontext)).thenReturn(List.of(Locale.FRENCH, Locale.ENGLISH));
             DocumentReference frenchDocumentReference = new DocumentReference("wiki", "Space", "Page", Locale.FRENCH);
             XWikiDocument frenchDocument = mock(XWikiDocument.class);
    +        DocumentAuthors frenchAuthors = mock(DocumentAuthors.class);
    +        when(frenchDocument.getAuthors()).thenReturn(frenchAuthors);
             when(baseDocument.getTranslatedDocument(Locale.FRENCH, xcontext)).thenReturn(frenchDocument);
             when(frenchDocument.getDocumentReference()).thenReturn(frenchDocumentReference);
     
             DocumentReference englishDocumentReference = new DocumentReference("wiki", "Space", "Page", Locale.ENGLISH);
             XWikiDocument englishDocument = mock(XWikiDocument.class);
    +        DocumentAuthors englishAuthors = mock(DocumentAuthors.class);
    +        when(englishDocument.getAuthors()).thenReturn(englishAuthors);
             when(baseDocument.getTranslatedDocument(Locale.ENGLISH, xcontext)).thenReturn(englishDocument);
             when(englishDocument.getDocumentReference()).thenReturn(englishDocumentReference);
     
    @@ -910,7 +955,7 @@ void updateAndTranslations() throws Exception
             updater.update(baseDocumentReference, oldLinkTarget, newLinkTarget);
     
             for (XWikiDocument xWikiDocument : documentsToUpdate) {
    -            verifyDocumentSave(xWikiDocument, "Renamed back-links.", false, false);
    +            verifyDocumentSave(xWikiDocument, false);
                 LinkBlock linkBlock =
                     (LinkBlock) xWikiDocument.getXDOM().getBlocks(mock(BlockMatcher.class), Block.Axes.DESCENDANT).get(0);
                 assertEquals("X.Y", linkBlock.getReference().getReference());
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.