VYPR
Critical severityNVD Advisory· Published Jun 23, 2023· Updated Dec 5, 2024

XWiki vulnerable to stored cross-site scripting via any wiki document and the displaycontent/rendercontent template

CVE-2023-34464

Description

XWiki Platform is a generic wiki platform offering runtime services for applications built on top of it. Starting in version 2.2.1 until versions 14.4.8, 14.10.5, and 15.1RC1 of org.xwiki.platform:xwiki-platform-web and any version prior to 14.4.8, 14.10.5, and 15.1.RC1 of org.xwiki.platform:xwiki-platform-web-templates, any user who can edit a document in a wiki like the user profile can create a stored cross-site scripting attack. The attack occurs by putting plain HTML code into that document and then tricking another user to visit that document with the displaycontent or rendercontent template and plain output syntax. If a user with programming rights is tricked into visiting such a URL, arbitrary actions be performed with this user's rights, impacting the confidentiality, integrity, and availability of the whole XWiki installation. This has been patched in XWiki 14.4.8, 14.10.5 and 15.1RC1 by setting the content type of the response to plain text when the output syntax is not an HTML syntax.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.xwiki.platform:xwiki-platform-webMaven
>= 2.2.1, < 14.4.814.4.8
org.xwiki.platform:xwiki-platform-web-templatesMaven
< 14.4.814.4.8
org.xwiki.platform:xwiki-platform-web-templatesMaven
>= 14.5, < 14.10.514.10.5
org.xwiki.platform:xwiki-platform-web-templatesMaven
>= 15.0-rc-1, < 15.1-rc-115.1-rc-1

Affected products

1

Patches

1
53e8292a31ec

XWIKI-20290: Set correct content type in rendercontent.vm

https://github.com/xwiki/xwiki-platformMichael HamannFeb 6, 2023via ghsa
2 files changed · +145 1
  • xwiki-platform-core/xwiki-platform-web/xwiki-platform-web-templates/src/main/resources/templates/rendercontent.vm+14 1 modified
    @@ -33,7 +33,20 @@
       $services.progress.pushLevel(1)
     #end
     $services.progress.startStep('Compute the content to display')
    -## Make sure we don't escape the content since we want HTML to be rendered
    +## Set the content type to text/plain when the output syntax is not HTML to avoid that other content is interpreted
    +## as HTML by the browser. This needs to be done before calling contentvars.vm as rendering the content can modify
    +## the content type when the document, e.g., produces JSON.
    +#if ($response.getContentType() != 'text/plain')
    +  #set ($outputSyntax = $xwiki.getAvailableRendererSyntax($request.outputSyntax, $request.outputSyntaxVersion))
    +  #if ($outputSyntax)
    +    #set ($syntaxType = $outputSyntax.type.toIdString())
    +    #if ($syntaxType != "xhtml" && $syntaxType != "html")
    +      $response.setContentType('text/plain')
    +    #end
    +  #end
    +#end
    +## Make sure we don't escape the content since non-HTML output like JSON is produced by some documents when plain
    +## output syntax is specified.
     #set ($noEscapeContent = true)
     #template("contentvars.vm")
     $services.progress.endStep()
    
  • xwiki-platform-core/xwiki-platform-web/xwiki-platform-web-templates/src/test/java/org/xwiki/web/DisplaycontentPageTest.java+131 0 added
    @@ -0,0 +1,131 @@
    +/*
    + * 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.web;
    +
    +import javax.inject.Inject;
    +
    +import org.junit.jupiter.api.BeforeEach;
    +import org.junit.jupiter.api.Test;
    +import org.xwiki.job.script.ProgressScripService;
    +import org.xwiki.model.reference.DocumentReference;
    +import org.xwiki.rendering.syntax.Syntax;
    +import org.xwiki.template.TemplateManager;
    +import org.xwiki.template.script.TemplateScriptService;
    +import org.xwiki.test.annotation.ComponentList;
    +import org.xwiki.test.page.HTML50ComponentList;
    +import org.xwiki.test.page.PageTest;
    +import org.xwiki.test.page.XWikiSyntax21ComponentList;
    +
    +import com.xpn.xwiki.XWikiException;
    +import com.xpn.xwiki.doc.XWikiDocument;
    +import com.xpn.xwiki.web.XWikiServletResponseStub;
    +
    +import static org.junit.jupiter.api.Assertions.assertEquals;
    +
    +/**
    + * Tests the {@code displaycontent.vm} template.
    + *
    + * @version $Id$
    + */
    +@HTML50ComponentList
    +@XWikiSyntax21ComponentList
    +@ComponentList({
    +    TemplateScriptService.class,
    +    ProgressScripService.class
    +})
    +class DisplaycontentPageTest extends PageTest
    +{
    +    private static final DocumentReference TEST_REFERENCE = new DocumentReference("xwiki", "space", "page");
    +
    +    private static final String TEMPLATE_NAME = "displaycontent.vm";
    +
    +    private static final String HTML_CONTENT_TYPE = "text/html; charset=utf-8";
    +
    +    private XWikiDocument document;
    +
    +    @Inject
    +    private TemplateManager templateManager;
    +
    +    @BeforeEach
    +    void setUp() throws XWikiException
    +    {
    +        this.document = new XWikiDocument(TEST_REFERENCE);
    +        this.document.setSyntax(Syntax.XWIKI_2_1);
    +        this.xwiki.saveDocument(this.document, this.context);
    +        this.context.setDoc(this.document);
    +
    +        // Allow setting the content type in the response, so we can assert it later. The default is consistent with
    +        // Utils#parseTemplate(String, boolean, XWikiContext).
    +        this.response = new XWikiServletResponseStub()
    +        {
    +            private String contentType = HTML_CONTENT_TYPE;
    +
    +            @Override
    +            public String getContentType()
    +            {
    +                return this.contentType;
    +            }
    +
    +            @Override
    +            public void setContentType(String type)
    +            {
    +                this.contentType = type;
    +            }
    +        };
    +        this.context.setResponse(this.response);
    +    }
    +
    +    @Test
    +    void renderHTML() throws Exception
    +    {
    +        this.document.setContent("Hello World");
    +        this.xwiki.saveDocument(this.document, this.context);
    +
    +        String result = this.templateManager.render(TEMPLATE_NAME).trim();
    +        assertEquals("<p>Hello World</p>", result);
    +        assertEquals(HTML_CONTENT_TYPE, this.response.getContentType());
    +    }
    +
    +    @Test
    +    void renderJSON() throws Exception
    +    {
    +        String json = "{\"hello\": \"world\"}";
    +        this.document.setContent(json
    +            + " {{velocity}}#set ($discard = $response.setContentType('application/json')){{/velocity}}");
    +        this.xwiki.saveDocument(this.document, this.context);
    +        this.request.put("outputSyntax", "plain");
    +
    +        String result = this.templateManager.render(TEMPLATE_NAME).trim();
    +        assertEquals(json, result);
    +        assertEquals("application/json", this.response.getContentType());
    +    }
    +
    +    @Test
    +    void renderPlain() throws Exception
    +    {
    +        this.document.setContent("<strong>Some HTML</strong>");
    +        this.xwiki.saveDocument(this.document, this.context);
    +        this.request.put("outputSyntax", "plain");
    +
    +        String result = this.templateManager.render(TEMPLATE_NAME).trim();
    +        assertEquals(this.document.getContent(), result);
    +        assertEquals("text/plain", this.response.getContentType());
    +    }
    +}
    

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.