CVE-2023-37914 (XML, published 2023-08-17T18:15Z)
Description: value: XWiki Platform is a generic wiki platform offering runtime services for applications built on top of it. Any user who can view `Invitation.WebHome` can execute arbitrary script macros including Groovy and Python macros that allow remote code execution including unrestricted read and write access to all wiki contents. This vulnerability has been patched on XWiki 14.4.8, 15.2-rc-1, and 14.10.6. Users are advised to upgrade. Users unable to upgrade may manually apply the patch on `Invitation.InvitationCommon` and `Invitation.InvitationConfig`, but there are otherwise no known workarounds for this vulnerability.
Severity: nan (CVSS v3 base score: 8.8)
Weakness: CWE-94 \u2014 Improper Control of Generation of Code ('Code Injection')
The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.
Repository: https://github.com/xwiki/xwiki-platform
Files changed:
xwiki-platform-core/xwiki-platform-invitation/xwiki-platform-invitation-ui/src/main/resources/Invitation/InvitationCommon.xml
xwiki-platform-core/xwiki-platform-invitation/xwiki-platform-invitation-ui/src/main/resources/Invitation/InvitationConfig.xml
xwiki-platform-core/xwiki-platform-invitation/xwiki-platform-invitation-ui/src/test/java/org/xwiki/invitation/InvitationCommonPageTest.java
xwiki-platform-core/xwiki-platform-invitation/xwiki-platform-invitation-ui/src/test/java/org/xwiki/invitation/InvitationConfigPageTest.java
Commit message: XWIKI-20421: Improved escaping of subjectLineTemplate


Vulnerable code:
      <subjectLineTemplate>{{velocity}}$services.localization.render('xe.invitation.emailContent.subjectLine', [$xcontext.getUser().replaceAll("^[^\.]*.", ""), $xwiki.getRequestURL().replaceAll("https?://([^/:]*).*$", "$1"), $!subjectLine]){{/velocity}}</subjectLineTemplate>
      <subjectLineTemplate>{{velocity}}$services.localization.render('xe.invitation.emailContent.subjectLine', [$xcontext.getUser().replaceAll("^[^\.]*.", ""), $xwiki.getRequestURL().replaceAll("https?://([^/:]*).*$", "$1"), $!subjectLine]){{/velocity}}</subjectLineTemplate>
import org.xwiki.rendering.syntax.Syntax;
        DocumentReference invitationCommonReference = new DocumentReference("xwiki", "Invitation", "InvitationCommon");
        Document document = Jsoup.parse(loadPage(invitationCommonReference).getRenderedContent(this.context));
        DocumentReference invitationCommonReference = new DocumentReference("xwiki", "Invitation", "InvitationCommon");
        Document document = Jsoup.parse(loadPage(invitationCommonReference).getRenderedContent(this.context));
        XWikiDocument invitationCommonDoc = loadPage(new DocumentReference("xwiki", "Invitation", "InvitationCommon"));
        DocumentReference reference = new DocumentReference("xwiki", "Invitation", "InvitationCommon");
        XWikiDocument invitationCommonDoc = loadPage(reference);
        DocumentReference reference = new DocumentReference("xwiki", "Invitation", "InvitationCommon");
        XWikiDocument invitationCommonDoc = loadPage(reference);
        loadPage(new DocumentReference("xwiki", "Invitation", "InvitationCommon"));
        page.setSyntax(Syntax.XWIKI_2_1);
    private static final DocumentReference INVITATION_CONFIG_DOCUMENT_REFERENCE =
        XWikiDocument invitationGuestActionsDocument = loadPage(INVITATION_CONFIG_DOCUMENT_REFERENCE);

Fixed code:
      <subjectLineTemplate>{{velocity wiki='false'}}$services.localization.render('xe.invitation.emailContent.subjectLine', [$xcontext.getUser().replaceAll("^[^\.]*.", ""), $xwiki.getRequestURL().replaceAll("https?://([^/:]*).*$", "$1"), $!subjectLine]){{/velocity}}</subjectLineTemplate>
      <subjectLineTemplate>{{velocity wiki='false'}}$services.localization.render('xe.invitation.emailContent.subjectLine', [$xcontext.getUser().replaceAll("^[^\.]*.", ""), $xwiki.getRequestURL().replaceAll("https?://([^/:]*).*$", "$1"), $!subjectLine]){{/velocity}}</subjectLineTemplate>
import static org.xwiki.rendering.syntax.Syntax.PLAIN_1_0;
import static org.xwiki.rendering.syntax.Syntax.XWIKI_2_0;
import static org.xwiki.rendering.syntax.Syntax.XWIKI_2_1;
    public static final DocumentReference INVITATION_COMMON_REFERENCE =
        new DocumentReference("xwiki", "Invitation", "InvitationCommon");

        Document document = Jsoup.parse(loadPage(INVITATION_COMMON_REFERENCE).getRenderedContent(this.context));
        Document document = Jsoup.parse(loadPage(INVITATION_COMMON_REFERENCE).getRenderedContent(this.context));
        XWikiDocument invitationCommonDoc = loadPage(INVITATION_COMMON_REFERENCE);
        XWikiDocument invitationCommonDoc = loadPage(INVITATION_COMMON_REFERENCE);
        XWikiDocument invitationCommonDoc = loadPage(INVITATION_COMMON_REFERENCE);
        loadPage(INVITATION_COMMON_REFERENCE);
        page.setSyntax(XWIKI_2_1);

    /**
     * Check if the value of subjectLine correctly escape its parameters.
     */
    @Test
    void subjectLineTemplate() throws Exception
    {
        com.xpn.xwiki.api.Document invitationCommonDocument =
            new com.xpn.xwiki.api.Document(loadPage(INVITATION_COMMON_REFERENCE), this.context);
        String value = String.valueOf(
            invitationCommonDocument.getObject("xwiki:Invitation.WebHome").getProperty("subjectLineTemplate")
                .getValue());
        this.oldcore.getScriptContext().setAttribute("subjectLine", "{{noscript/}}", GLOBAL_SCOPE);
        com.xpn.xwiki.api.Document testDocument = new com.xpn.xwiki.api.Document(
            this.xwiki.getDocument(new DocumentReference("xwiki", "Space", "Test"), this.context), this.context);
        String renderedContent = testDocument.getRenderedContent(value, XWIKI_2_0.toIdString(), PLAIN_1_0.toIdString());
        assertEquals("xe.invitation.emailContent.subjectLine [XWikiGuest, null, {{noscript/}}]", renderedContent);
    }
import static javax.script.ScriptContext.GLOBAL_SCOPE;
import static org.xwiki.rendering.syntax.Syntax.PLAIN_1_0;
import static org.xwiki.rendering.syntax.Syntax.XWIKI_2_0;
    private static final DocumentReference INVITATION_CONFIG_REFERENCE =
        XWikiDocument invitationGuestActionsDocument = loadPage(INVITATION_CONFIG_REFERENCE);

    @Test
    void subjectLineTemplate() throws Exception
    {
        com.xpn.xwiki.api.Document invitationConfigDocument =
            new com.xpn.xwiki.api.Document(loadPage(INVITATION_CONFIG_REFERENCE), this.context);
        String value = String.valueOf(
            invitationConfigDocument.getObject("xwiki:Invitation.WebHome").getProperty("subjectLineTemplate")
                .getValue());
        this.oldcore.getScriptContext().setAttribute("subjectLine", "{{noscript/}}", GLOBAL_SCOPE);
        com.xpn.xwiki.api.Document testDocument = new com.xpn.xwiki.api.Document(
            this.xwiki.getDocument(new DocumentReference("xwiki", "Space", "Test"), this.context), this.context);
        String renderedContent = testDocument.getRenderedContent(value, XWIKI_2_0.toIdString(), PLAIN_1_0.toIdString());
        assertEquals("xe.invitation.emailContent.subjectLine [XWikiGuest, null, {{noscript/}}]", renderedContent);
    }