CVE-2023-40572 (published 2023-08-24T02:15Z)

XWiki Platform is a generic wiki platform offering runtime services for applications built on top of it. The create action is vulnerable to a CSRF attack, allowing script and thus remote code execution when targeting a user with script/programming right, thus compromising the confidentiality, integrity and availability of the whole XWiki installation. When a user with script right views this image and a log message `ERROR foo - Script executed!` appears in the log, the XWiki installation is vulnerable. This has been patched in XWiki 14.10.9 and 15.4RC1 by requiring a CSRF token for the actual page creation.

CVSS v3 base score: 8.0, HIGH (CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-352
cwe_name: Cross-Site Request Forgery (CSRF)
description: The web application does not, or can not, sufficiently verify whether a well-formed, valid, consistent request was intentionally provided by the user who submitted the request.
extended_description: When a web server is designed to receive a request from a client without any mechanism for verifying that it was intentionally sent, then it might be possible for an attacker to trick a client into making an unintentional request to the web server which will be treated as an authentic request. This can be done via a URL, image load, XMLHttpRequest, etc. and can result in exposure of data or unintended code execution.
         

Fix information:
repo_url: https://github.com/xwiki/xwiki-platform
commit_details: repo_url: https://github.com/xwiki/xwiki-platform
author: Michael Hamann
author_date: 2023-04-18 15:09:51+02:00
msg: XWIKI-20849: Require a CSRF token in the create action
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: CreateAction.java
change_type: ModificationType.MODIFY
diff: @@ -23,6 +23,7 @@
 import java.util.Locale;
 import java.util.Map;
 
+import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Provider;
 import javax.inject.Singleton;
@@ -96,6 +97,9 @@ public class CreateAction extends XWikiAction
      */
     private static final String LOCAL_SERIALIZER_HINT = "local";
 
+    @Inject
+    private CSRFToken csrf;
+
     /**
      * The action to perform when creating a new page from a template.
      *
@@ -185,9 +189,12 @@ public String render(XWikiContext context) throws XWikiException
         checkRights(newDocumentReference.getLastSpaceReference(), context);
 
         // Check if the document to create already exists and if it respects the name strategy
+        // Also check the CSRF token.
         XWikiDocument newDocument = context.getWiki().getDocument(newDocumentReference, context);
         if (handler.isDocumentAlreadyExisting(newDocument) || handler.isDocumentPathTooLong(newDocumentReference)
-            || !this.isEntityReferenceNameValid(newDocumentReference)) {
+            || !this.isEntityReferenceNameValid(newDocumentReference)
+            || !this.csrf.isTokenValid(context.getRequest().getParameter("form_token")))
+        {
             return CREATE_TEMPLATE;
         }
 
@@ -334,8 +341,7 @@ private String getRedirectParameters(String parent, String title, String templat
             redirectParams += "&title=" + Util.encodeURI(title, null);
         }
         // Both the save and the edit action might require a CSRF token
-        CSRFToken csrf = Utils.getComponent(CSRFToken.class);
-        redirectParams += "&form_token=" + Util.encodeURI(csrf.getToken(), null);
+        redirectParams += "&form_token=" + Util.encodeURI(this.csrf.getToken(), null);
 
         return redirectParams;
     }

programming_language: Java
filename: CreateActionTest.java
change_type: ModificationType.MODIFY
diff: @@ -72,6 +72,8 @@
 @OldcoreTest
 class CreateActionTest
 {
+    private static final String CSRF_TOKEN_VALUE = "token4234343";
+
     @InjectMockitoOldcore
     MockitoOldcore oldcore;
 
@@ -125,6 +127,10 @@ public void beforeEach() throws Exception
         when(this.mockRequest.get("type")).thenReturn("plain");
 
         this.oldcore.getMocker().registerMockComponent(ObservationManager.class);
+
+        when(this.csrfToken.getToken()).thenReturn(CSRF_TOKEN_VALUE);
+        when(this.csrfToken.isTokenValid(CSRF_TOKEN_VALUE)).thenReturn(true);
+        when(this.mockRequest.getParameter("form_token")).thenReturn(CSRF_TOKEN_VALUE);
     }
 
     @Test
@@ -137,8 +143,6 @@ void newDocumentFromURL() throws Exception
         when(document.isNew()).thenReturn(true);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token42";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Run the action
         String result = action.render(context);
@@ -149,11 +153,42 @@ void newDocumentFromURL() throws Exception
         assertNull(result);
 
         verify(mockURLFactory).createURL("X", "Y", "edit",
-            "template=&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue,
+            "template=&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE,
             null, "xwiki",
             context);
     }
 
+    @Test
+    void newDocumentFromURLWithInvalidToken() throws Exception
+    {
+        // new document = xwiki:X.Y
+        DocumentReference documentReference = new DocumentReference("xwiki", Arrays.asList("X"), "Y");
+        XWikiDocument document = mock(XWikiDocument.class);
+        when(document.getDocumentReference()).thenReturn(documentReference);
+        when(document.isNew()).thenReturn(true);
+        when(document.getLocalReferenceMaxLength()).thenReturn(255);
+        this.context.setDoc(document);
+
+        // Submit an invalid token
+        when(this.mockRequest.getParameter("form_token")).thenReturn("fakeToken");
+
+        // Run the action
+        String result = this.action.render(this.context);
+
+        // The tests are below this line!
+
+        // Verify that the create template is rendered, so the UI is displayed for the user to re-submit with the
+        // form token.
+        assertEquals("create", result);
+
+        // Verify that we got until the token validation.
+        verify(this.csrfToken).isTokenValid("fakeToken");
+
+        // We should not get this far so no redirect should be done, just the template will be rendered.
+        verify(this.mockURLFactory, never()).createURL(any(), any(), any(), any(), any(), any(),
+            any(XWikiContext.class));
+    }
+
     @Test
     void newDocumentButNonTerminalFromURL() throws Exception
     {
@@ -164,8 +199,6 @@ void newDocumentButNonTerminalFromURL() throws Exception
         when(document.isNew()).thenReturn(true);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token432";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Pass the tocreate=nonterminal request parameter
         when(mockRequest.getParameter("tocreate")).thenReturn("nonterminal");
@@ -178,8 +211,11 @@ void newDocumentButNonTerminalFromURL() throws Exception
         // Verify null is returned (this means the response has been returned)
         assertNull(result);
 
+        // Verify that the token has been validated.
+        verify(this.csrfToken).isTokenValid(CSRF_TOKEN_VALUE);
+
         verify(mockURLFactory).createURL("X.Y", "WebHome", "edit",
-            "template=&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue, null,
+            "template=&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE, null,
             "xwiki", context);
     }
 
@@ -216,8 +252,6 @@ void newDocumentWebHomeTopLevelFromURL() throws Exception
         when(document.isNew()).thenReturn(true);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token4234";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Run the action
         String result = action.render(context);
@@ -229,7 +263,7 @@ void newDocumentWebHomeTopLevelFromURL() throws Exception
 
         // Note: The title is not "WebHome", but "X" (the space's name) to avoid exposing "WebHome" in the UI.
         verify(mockURLFactory).createURL("X", "WebHome", "edit",
-            "template=&parent=Main.WebHome&title=X&form_token=" + csrfTokenValue, null, "xwiki",
+            "template=&parent=Main.WebHome&title=X&form_token=" + CSRF_TOKEN_VALUE, null, "xwiki",
             context);
     }
 
@@ -243,8 +277,6 @@ void newDocumentWebHomeFromURL() throws Exception
         when(document.isNew()).thenReturn(true);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token34342";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Run the action
         String result = action.render(context);
@@ -257,7 +289,7 @@ void newDocumentWebHomeFromURL() throws Exception
         // Note1: The bebavior is the same for both a top level space and a child space WebHome.
         // Note2: The title is not "WebHome", but "Y" (the space's name) to avoid exposing "WebHome" in the UI.
         verify(mockURLFactory).createURL("X.Y", "WebHome", "edit",
-            "template=&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue, null,
+            "template=&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE, null,
             "xwiki", context);
     }
 
@@ -271,8 +303,6 @@ void newDocumentWebHomeButTerminalFromURL() throws Exception
         when(document.isNew()).thenReturn(true);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token4234343";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Pass the tocreate=terminal request parameter
         when(mockRequest.getParameter("tocreate")).thenReturn("terminal");
@@ -287,7 +317,7 @@ void newDocumentWebHomeButTerminalFromURL() throws Exception
 
         // Note: We are creating X.Y instead of X.Y.WebHome because the tocreate parameter says "terminal".
         verify(mockURLFactory).createURL("X", "Y", "edit",
-            "template=&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue, null, "xwiki",
+            "template=&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE, null, "xwiki",
             context);
     }
 
@@ -355,8 +385,6 @@ void existingDocumentFromUI() throws Exception
         when(document.isNew()).thenReturn(false);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token424345";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI spaceReference=X&name=Y
         when(mockRequest.getParameter("spaceReference")).thenReturn("X");
@@ -372,7 +400,7 @@ void existingDocumentFromUI() throws Exception
 
         // Note: We are creating X.Y.WebHome since we default to non-terminal documents.
         verify(mockURLFactory).createURL("X.Y", "WebHome", "edit",
-            "template=&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue, null,
+            "template=&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE, null,
             "xwiki", context);
     }
 
@@ -386,8 +414,6 @@ void existingDocumentFromUICheckEscaping() throws Exception
         when(document.isNew()).thenReturn(false);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token42124343";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI spaceReference=X.Y&name=Z
         when(mockRequest.getParameter("spaceReference")).thenReturn("X.Y");
@@ -403,7 +429,7 @@ void existingDocumentFromUICheckEscaping() throws Exception
 
         // Note: We are creating X.Y.Z.WebHome since we default to non-terminal documents.
         verify(mockURLFactory).createURL("X.Y.Z", "WebHome", "edit",
-            "template=&parent=Main.WebHome&title=Z&form_token=" + csrfTokenValue, null,
+            "template=&parent=Main.WebHome&title=Z&form_token=" + CSRF_TOKEN_VALUE, null,
             "xwiki", context);
     }
 
@@ -417,8 +443,6 @@ void existingDocumentTerminalFromUI() throws Exception
         when(document.isNew()).thenReturn(false);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token424334466";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI spaceReference=X&name=Y&tocreate=terminal
         when(mockRequest.getParameter("spaceReference")).thenReturn("X");
@@ -435,7 +459,7 @@ void existingDocumentTerminalFromUI() throws Exception
 
         // Note: We are creating X.Y instead of X.Y.WebHome because the tocreate parameter says "terminal".
         verify(mockURLFactory).createURL("X", "Y", "edit",
-            "template=&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue, null, "xwiki",
+            "template=&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE, null, "xwiki",
             context);
     }
 
@@ -449,8 +473,6 @@ void existingDocumentTerminalFromUICheckEscaping() throws Exception
         when(document.isNew()).thenReturn(false);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token429988";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI spaceReference=X.Y&name=Z&tocreate=termina
         when(mockRequest.getParameter("spaceReference")).thenReturn("X.Y");
@@ -467,7 +489,7 @@ void existingDocumentTerminalFromUICheckEscaping() throws Exception
 
         // Note: We are creating X.Y.Z instead of X.Y.Z.WebHome because the tocreate parameter says "terminal".
         verify(mockURLFactory).createURL("X.Y", "Z", "edit",
-            "template=&parent=Main.WebHome&title=Z&form_token=" + csrfTokenValue, null, "xwiki",
+            "template=&parent=Main.WebHome&title=Z&form_token=" + CSRF_TOKEN_VALUE, null, "xwiki",
             context);
     }
 
@@ -581,8 +603,6 @@ void existingDocumentFromUITopLevelDocument() throws Exception
         when(document.isNew()).thenReturn(false);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token42009";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI name=Y
         when(mockRequest.getParameter("name")).thenReturn("Y");
@@ -597,7 +617,7 @@ void existingDocumentFromUITopLevelDocument() throws Exception
 
         // Note: We are creating X.Y.WebHome since we default to non-terminal documents.
         verify(mockURLFactory).createURL("Y", "WebHome", "edit",
-            "template=&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue, null, "xwiki",
+            "template=&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE, null, "xwiki",
             context);
     }
 
@@ -615,8 +635,6 @@ void existingDocumentFromUIDeprecated() throws Exception
         when(document.isNew()).thenReturn(false);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token4233311";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI space=X&page=Y
         when(mockRequest.getParameter("space")).thenReturn("X");
@@ -632,7 +650,7 @@ void existingDocumentFromUIDeprecated() throws Exception
 
         // Note: We are creating X.Y since the deprecated parameters were creating terminal documents by default.
         verify(mockURLFactory).createURL("X", "Y", "edit",
-            "template=&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue, null, "xwiki",
+            "template=&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE, null, "xwiki",
             context);
     }
 
@@ -646,8 +664,6 @@ void existingDocumentFromUIDeprecatedCheckEscaping() throws Exception
         when(document.isNew()).thenReturn(false);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token422112455";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI space=X.Y&page=Z
         when(mockRequest.getParameter("space")).thenReturn("X.Y");
@@ -664,7 +680,7 @@ void existingDocumentFromUIDeprecatedCheckEscaping() throws Exception
         // Note1: The space parameter was previously considered as space name, not space reference, so it is escaped.
         // Note2: We are creating X\.Y.Z since the deprecated parameters were creating terminal documents by default.
         verify(mockURLFactory).createURL("X\\.Y", "Z", "edit",
-            "template=&parent=Main.WebHome&title=Z&form_token=" + csrfTokenValue, null, "xwiki",
+            "template=&parent=Main.WebHome&title=Z&form_token=" + CSRF_TOKEN_VALUE, null, "xwiki",
             context);
     }
 
@@ -678,8 +694,6 @@ void existingDocumentNonTerminalFromUIDeprecated() throws Exception
         when(document.isNew()).thenReturn(false);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token42778900";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI space=X&tocreate=space
         when(mockRequest.getParameter("space")).thenReturn("X");
@@ -695,7 +709,7 @@ void existingDocumentNonTerminalFromUIDeprecated() throws Exception
 
         // Note: We are creating X.WebHome because the tocreate parameter says "space".
         verify(mockURLFactory).createURL("X", "WebHome", "edit",
-            "template=&parent=Main.WebHome&title=X&form_token=" + csrfTokenValue, null, "xwiki",
+            "template=&parent=Main.WebHome&title=X&form_token=" + CSRF_TOKEN_VALUE, null, "xwiki",
             context);
     }
 
@@ -709,8 +723,6 @@ void existingDocumentNonTerminalFromUIDeprecatedIgnoringPage() throws Exception
         when(document.isNew()).thenReturn(false);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token4344119982";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI space=X&page=Y&tocreate=space
         when(mockRequest.getParameter("space")).thenReturn("X");
@@ -728,7 +740,7 @@ void existingDocumentNonTerminalFromUIDeprecatedIgnoringPage() throws Exception
         // Note: We are creating X.WebHome instead of X.Y because the tocreate parameter says "space" and the page
         // parameter is ignored.
         verify(mockURLFactory).createURL("X", "WebHome", "edit",
-            "template=&parent=Main.WebHome&title=X&form_token=" + csrfTokenValue, null, "xwiki",
+            "template=&parent=Main.WebHome&title=X&form_token=" + CSRF_TOKEN_VALUE, null, "xwiki",
             context);
     }
 
@@ -742,8 +754,6 @@ void existingDocumentNonTerminalFromUIDeprecatedCheckEscaping() throws Exception
         when(document.isNew()).thenReturn(false);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token425553";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI space=X.Y&tocreate=space
         when(mockRequest.getParameter("space")).thenReturn("X.Y");
@@ -760,7 +770,7 @@ void existingDocumentNonTerminalFromUIDeprecatedCheckEscaping() throws Exception
         // Note1: The space parameter was previously considered as space name, not space reference, so it is escaped.
         // Note2: We are creating X\.Y.WebHome because the tocreate parameter says "space".
         verify(mockURLFactory).createURL("X\\.Y", "WebHome", "edit",
-            "template=&parent=Main.WebHome&title=X.Y&form_token=" + csrfTokenValue, null,
+            "template=&parent=Main.WebHome&title=X.Y&form_token=" + CSRF_TOKEN_VALUE, null,
             "xwiki", context);
     }
 
@@ -901,8 +911,6 @@ void existingDocumentFromUITemplateProviderSpecified() throws Exception
         when(document.isNew()).thenReturn(false);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token42008766";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI spaceReference=X&name=Y&templateProvider=XWiki.MyTemplateProvider
         String templateProviderFullName = "XWiki.MyTemplateProvider";
@@ -924,7 +932,7 @@ void existingDocumentFromUITemplateProviderSpecified() throws Exception
 
         // Note: We are creating X.Y and using the template extracted from the template provider.
         verify(mockURLFactory).createURL("X.Y", "WebHome", "edit",
-            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue, null, "xwiki",
+            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE, null, "xwiki",
             context);
     }
 
@@ -977,8 +985,6 @@ void existingDocumentFromUITemplateProviderSpecifiedRestrictionExistsOnParentSpa
         when(document.isNew()).thenReturn(false);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token4221098";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI spaceReference=X.Y.Z&name=W&templateProvider=XWiki.MyTemplateProvider
         String templateProviderFullName = "XWiki.MyTemplateProvider";
@@ -1004,7 +1010,7 @@ void existingDocumentFromUITemplateProviderSpecifiedRestrictionExistsOnParentSpa
         // document
         // Note2: We are creating X.Y.Z.W and using the template extracted from the template provider.
         verify(mockURLFactory).createURL("X.Y.Z.W", "WebHome", "edit",
-            "template=XWiki.MyTemplate&parent=Main.WebHome&title=W&form_token=" + csrfTokenValue,
+            "template=XWiki.MyTemplate&parent=Main.WebHome&title=W&form_token=" + CSRF_TOKEN_VALUE,
             null, "xwiki", context);
     }
 
@@ -1132,8 +1138,6 @@ void newDocumentWebHomeFromURLTemplateProviderSpecifiedTerminal() throws Excepti
         when(document.isNew()).thenReturn(true);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token42988733";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Specifying a template provider in the URL: templateprovider=XWiki.MyTemplateProvider
         String templateProviderFullName = "XWiki.MyTemplateProvider";
@@ -1155,7 +1159,7 @@ void newDocumentWebHomeFromURLTemplateProviderSpecifiedTerminal() throws Excepti
         // Note: We are creating the document X.Y as terminal and using a template, as specified in the template
         // provider.
         verify(mockURLFactory).createURL("X", "Y", "edit",
-            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue,
+            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE,
             null, "xwiki", context);
     }
 
@@ -1169,8 +1173,6 @@ void newDocumentWebHomeFromURLTemplateProviderSpecifiedTerminalOverriddenFromUIT
         when(document.isNew()).thenReturn(true);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token4222113555";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Specifying a template provider in the URL: templateprovider=XWiki.MyTemplateProvider
         String templateProviderFullName = "XWiki.MyTemplateProvider";
@@ -1193,7 +1195,7 @@ void newDocumentWebHomeFromURLTemplateProviderSpecifiedTerminalOverriddenFromUIT
         // Note: We are creating the document X.Y.WebHome as non-terminal even if the template provider says otherwise.
         // Also using a template, as specified in the template provider.
         verify(mockURLFactory).createURL("X.Y", "WebHome", "edit",
-            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue,
+            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE,
             null, "xwiki", context);
     }
 
@@ -1207,8 +1209,6 @@ void newDocumentFromURLTemplateProviderSpecifiedNonTerminal() throws Exception
         when(document.isNew()).thenReturn(true);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token4200983331";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Specifying a template provider in the URL: templateprovider=XWiki.MyTemplateProvider
         String templateProviderFullName = "XWiki.MyTemplateProvider";
@@ -1230,7 +1230,7 @@ void newDocumentFromURLTemplateProviderSpecifiedNonTerminal() throws Exception
         // Note: We are creating the document X.Y as terminal and using a template, as specified in the template
         // provider.
         verify(mockURLFactory).createURL("X.Y", "WebHome", "edit",
-            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue,
+            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE,
             null, "xwiki", context);
     }
 
@@ -1244,8 +1244,6 @@ void newDocumentFromURLTemplateProviderSpecifiedNonTerminalButOverriddenFromUITe
         when(document.isNew()).thenReturn(true);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token42234456";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Specifying a template provider in the URL: templateprovider=XWiki.MyTemplateProvider
         String templateProviderFullName = "XWiki.MyTemplateProvider";
@@ -1268,7 +1266,7 @@ void newDocumentFromURLTemplateProviderSpecifiedNonTerminalButOverriddenFromUITe
         // Note: We are creating the document X.Y as terminal and using a template, as specified in the template
         // provider.
         verify(mockURLFactory).createURL("X", "Y", "edit",
-            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue,
+            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE,
             null, "xwiki", context);
     }
 
@@ -1283,8 +1281,6 @@ void existingDocumentFromUITemplateSpecified() throws Exception
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
 
         context.setDoc(document);
-        String csrfTokenValue = "token4298833";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI spaceReference=X&name=Y&template=XWiki.MyTemplate
         String templateDocumentFullName = "XWiki.MyTemplate";
@@ -1307,7 +1303,7 @@ void existingDocumentFromUITemplateSpecified() throws Exception
 
         // Note: We are creating X.Y.WebHome and using the template specified in the request.
         verify(mockURLFactory).createURL("X.Y", "WebHome", "edit",
-            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue,
+            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE,
             null, "xwiki", context);
     }
 
@@ -1321,8 +1317,6 @@ void existingDocumentFromUITemplateProviderSpecifiedTerminal() throws Exception
         when(document.isNew()).thenReturn(false);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token4244112";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI spaceReference=X&name=Y&templateProvider=XWiki.MyTemplateProvider
         String templateProviderFullName = "XWiki.MyTemplateProvider";
@@ -1347,7 +1341,7 @@ void existingDocumentFromUITemplateProviderSpecifiedTerminal() throws Exception
         // Note: We are creating the document X.Y as terminal and using a template, as specified in the template
         // provider.
         verify(mockURLFactory).createURL("X", "Y", "edit",
-            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue,
+            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE,
             null, "xwiki", context);
     }
 
@@ -1361,8 +1355,6 @@ void existingDocumentFromUITemplateProviderSpecifiedTerminalOverridenFromUIToNon
         when(document.isNew()).thenReturn(false);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token422555987";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI spaceReference=X&name=Y&templateProvider=XWiki.MyTemplateProvider
         String templateProviderFullName = "XWiki.MyTemplateProvider";
@@ -1388,7 +1380,7 @@ void existingDocumentFromUITemplateProviderSpecifiedTerminalOverridenFromUIToNon
         // Note: We are creating the document X.Y.WebHome as non-terminal, even if the template provider says otherwise.
         // Also using a template, as specified in the template provider.
         verify(mockURLFactory).createURL("X.Y", "WebHome", "edit",
-            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue,
+            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE,
             null, "xwiki", context);
     }
 
@@ -1402,8 +1394,6 @@ void existingDocumentFromUITemplateProviderSpecifiedNonTerminal() throws Excepti
         when(document.isNew()).thenReturn(false);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token424111553";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI spaceReference=X&name=Y&templateProvider=XWiki.MyTemplateProvider
         String templateProviderFullName = "XWiki.MyTemplateProvider";
@@ -1428,7 +1418,7 @@ void existingDocumentFromUITemplateProviderSpecifiedNonTerminal() throws Excepti
         // Note: We are creating the document X.Y.WebHome as non-terminal and using a template, as specified in the
         // template provider.
         verify(mockURLFactory).createURL("X.Y", "WebHome", "edit",
-            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue,
+            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE,
             null, "xwiki", context);
     }
 
@@ -1442,8 +1432,6 @@ void existingDocumentFromUITemplateProviderSpecifiedNonTerminalOverridenFromUITo
         when(document.isNew()).thenReturn(false);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token42008733";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI spaceReference=X&name=Y&templateProvider=XWiki.MyTemplateProvider
         String templateProviderFullName = "XWiki.MyTemplateProvider";
@@ -1469,7 +1457,7 @@ void existingDocumentFromUITemplateProviderSpecifiedNonTerminalOverridenFromUITo
         // Note: We are creating the document X.Y as terminal, even if the template provider says otherwise.
         // Also using a template, as specified in the template provider.
         verify(mockURLFactory).createURL("X", "Y", "edit",
-            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue,
+            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE,
             null, "xwiki", context);
     }
 
@@ -1483,8 +1471,6 @@ void newDocumentWebHomeFromURLTemplateProviderSpecifiedButOldPageType() throws E
         when(document.isNew()).thenReturn(true);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token423366";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Specifying a template provider in the URL: templateprovider=XWiki.MyTemplateProvider
         String templateProviderFullName = "XWiki.MyTemplateProvider";
@@ -1507,7 +1493,7 @@ void newDocumentWebHomeFromURLTemplateProviderSpecifiedButOldPageType() throws E
         // property and it used the old "page" type instead. Also using a template, as specified in the template
         // provider.
         verify(mockURLFactory).createURL("X", "Y", "edit",
-            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue,
+            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE,
             null, "xwiki", context);
     }
 
@@ -1522,8 +1508,6 @@ void newDocumentWebHomeFromURLTemplateProviderSpecifiedButOldPageTypeButOverridd
         when(document.isNew()).thenReturn(true);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token4265677398";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Specifying a template provider in the URL: templateprovider=XWiki.MyTemplateProvider
         String templateProviderFullName = "XWiki.MyTemplateProvider";
@@ -1547,7 +1531,7 @@ void newDocumentWebHomeFromURLTemplateProviderSpecifiedButOldPageTypeButOverridd
         // specify a "terminal" property and it used the old "page" type, the UI explicitly asked for a non-terminal
         // document. Also using a template, as specified in the template provider.
         verify(mockURLFactory).createURL("X.Y", "WebHome", "edit",
-            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue,
+            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE,
             null, "xwiki", context);
     }
 
@@ -1561,8 +1545,6 @@ void existingDocumentFromUITemplateProviderSpecifiedButOldSpaceType() throws Exc
         when(document.isNew()).thenReturn(false);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token421198337";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI spaceReference=X&name=Y&templateProvider=XWiki.MyTemplateProvider
         String templateProviderFullName = "XWiki.MyTemplateProvider";
@@ -1587,7 +1569,7 @@ void existingDocumentFromUITemplateProviderSpecifiedButOldSpaceType() throws Exc
         // property and we fallback on the "type" property's value. Also using the template extracted from the template
         // provider.
         verify(mockURLFactory).createURL("X.Y", "WebHome", "edit",
-            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue,
+            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE,
             null, "xwiki", context);
     }
 
@@ -1601,8 +1583,6 @@ void existingDocumentFromUITemplateProviderSpecifiedButOldSpaceTypeButOverridenF
         when(document.isNew()).thenReturn(false);
         when(document.getLocalReferenceMaxLength()).thenReturn(255);
         context.setDoc(document);
-        String csrfTokenValue = "token429866333";
-        when(this.csrfToken.getToken()).thenReturn(csrfTokenValue);
 
         // Submit from the UI spaceReference=X&name=Y&templateProvider=XWiki.MyTemplateProvider
         String templateProviderFullName = "XWiki.MyTemplateProvider";
@@ -1627,7 +1607,7 @@ void existingDocumentFromUITemplateProviderSpecifiedButOldSpaceTypeButOverridenF
         // Note: We are creating X.Y as terminal, since it is overriden from the UI, regardless of any backwards
         // compatibility resolutions. Also using the template extracted from the template provider.
         verify(mockURLFactory).createURL("X", "Y", "edit",
-            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + csrfTokenValue,
+            "template=XWiki.MyTemplate&parent=Main.WebHome&title=Y&form_token=" + CSRF_TOKEN_VALUE,
             null, "xwiki", context);
     }
 

programming_language: Java
filename: createinline.vm
change_type: ModificationType.MODIFY
diff: @@ -276,6 +276,7 @@
   ## By the past, it was "xwiki/create.js" which created this field, but it was causing problems when the user sent the
   ## form before the JavaScript code was executed.
   <input type="hidden" name="templateprovider" id="templateprovider" value="" />
+  <input type="hidden" name="form_token" value="$!{escapetool.xml($services.csrf.getToken())}"/>
 
   <div class='row'>
     ## Hide the first column when displayed in an AJAX call by clicking on a Wanted Link (because we know the target

programming_language: Python