VYPR
High severityNVD Advisory· Published Feb 4, 2022· Updated Apr 22, 2025

Cross-Site Request Forgery in xwiki-platform

CVE-2021-32732

Description

Impact

It's possible to know if a user has or not an account in a wiki related to an email address, and which username(s) is actually tied to that email by forging a request to the Forgot username page. Note that since this page does not have a CSRF check it's quite easy to perform a lot of those requests.

Patches

This issue has been patched in XWiki 12.10.5 and 13.2RC1. Two different patches are provided: - a first one to fix the CSRF problem - a more complex one that now relies on sending an email for the Forgot username process.

Workarounds

It's possible to fix the problem without uprading by editing the ForgotUsername page in version below 13.x, to use the following code: https://github.com/xwiki/xwiki-platform/blob/69548c0320cbd772540cf4668743e69f879812cf/xwiki-platform-core/xwiki-platform-administration/xwiki-platform-administration-ui/src/main/resources/XWiki/ForgotUsername.xml#L39-L123 In version after 13.x it's also possible to edit manually the forgotusername.vm file, but it's really encouraged to upgrade the version here.

References * https://jira.xwiki.org/browse/XWIKI-18384 * https://jira.xwiki.org/browse/XWIKI-18408

For more information

If you have any questions or comments about this advisory: * Open an issue in Jira XWiki * Email us at security ML

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.xwiki.platform:xwiki-platform-administration-uiMaven
< 12.10.512.10.5
org.xwiki.platform:xwiki-platform-administration-uiMaven
>= 13.0, < 13.2RC113.2RC1

Affected products

1

Patches

2
69548c0320cb

XWIKI-18408: Wrong check in forgot username

https://github.com/xwiki/xwiki-platformSimon UrliMar 9, 2021via ghsa
1 file changed · +9 2
  • xwiki-platform-core/xwiki-platform-administration/xwiki-platform-administration-ui/src/main/resources/XWiki/ForgotUsername.xml+9 2 modified
    @@ -38,12 +38,19 @@
       <hidden>true</hidden>
       <content>{{velocity}}
     #set($email = "$!request.get('e')")
    -#if($email == '')
    +#if($email == '' || !$services.csrf.isTokenValid($request.form_token))
     {{translation key="xe.admin.forgotUsername.instructions"/}}
     
     {{html}}
       &lt;form method="post" action="$doc.getURL()" class="xformInline"&gt;
    -    &lt;div&gt;&lt;label for="e"&gt;$services.localization.render('xe.admin.forgotUsername.email.label')&lt;/label&gt; &lt;input type="text" id="e" name="e"/&gt; &lt;span class="buttonwrapper"&gt;&lt;input type="submit" value="$services.localization.render('xe.admin.forgotUsername.submit')" class="button"/&gt;&lt;/span&gt;&lt;/div&gt;
    +    &lt;div&gt;
    +      &lt;label for="e"&gt;$services.localization.render('xe.admin.forgotUsername.email.label')&lt;/label&gt;
    +      &lt;input type="text" id="e" name="e"/&gt;
    +      &lt;input type="hidden" name="form_token" value="$services.csrf.getToken()"/&gt;
    +      &lt;span class="buttonwrapper"&gt;
    +        &lt;input type="submit" value="$services.localization.render('xe.admin.forgotUsername.submit')" class="button"/&gt;
    +      &lt;/span&gt;
    +    &lt;/div&gt;
       &lt;/form&gt;
     {{/html}}
     
    
f0440dfcbba7

XWIKI-18384: Improve ForgotUsername process

https://github.com/xwiki/xwiki-platformSimon UrliMar 5, 2021via ghsa
5 files changed · +400 32
  • xwiki-platform-core/xwiki-platform-administration/xwiki-platform-administration-test/xwiki-platform-administration-test-docker/src/test/it/org/xwiki/administration/test/ui/ForgotUsernameIT.java+161 16 modified
    @@ -19,12 +19,30 @@
      */
     package org.xwiki.administration.test.ui;
     
    +import java.util.HashMap;
    +import java.util.Map;
    +
    +import javax.mail.Address;
    +import javax.mail.BodyPart;
    +import javax.mail.MessagingException;
    +import javax.mail.Multipart;
    +import javax.mail.internet.MimeMessage;
    +
    +import org.apache.commons.io.IOUtils;
    +import org.junit.jupiter.api.AfterEach;
    +import org.junit.jupiter.api.BeforeEach;
     import org.junit.jupiter.api.Test;
     import org.xwiki.administration.test.po.ForgotUsernameCompletePage;
     import org.xwiki.administration.test.po.ForgotUsernamePage;
    +import org.xwiki.test.docker.junit5.TestConfiguration;
     import org.xwiki.test.docker.junit5.UITest;
    +import org.xwiki.test.integration.junit.LogCaptureConfiguration;
     import org.xwiki.test.ui.TestUtils;
     
    +import com.icegreen.greenmail.util.GreenMail;
    +import com.icegreen.greenmail.util.ServerSetupTest;
    +
    +import static org.junit.jupiter.api.Assertions.assertEquals;
     import static org.junit.jupiter.api.Assertions.assertFalse;
     import static org.junit.jupiter.api.Assertions.assertTrue;
     
    @@ -34,44 +52,171 @@
      * @version $Id$
      * @since 11.10
      */
    -@UITest
    +@UITest(sshPorts = {
    +    // Open the GreenMail port so that the XWiki instance inside a Docker container can use the SMTP server provided
    +    // by GreenMail running on the host.
    +    3025
    +},
    +    properties = {
    +        // The Mail module contributes a Hibernate mapping that needs to be added to hibernate.cfg.xml
    +        "xwikiDbHbmCommonExtraMappings=mailsender.hbm.xml"
    +    },
    +    extraJARs = {
    +        // It's currently not possible to install a JAR contributing a Hibernate mapping file as an Extension. Thus
    +        // we need to provide the JAR inside WEB-INF/lib. See https://jira.xwiki.org/browse/XWIKI-8271
    +        "org.xwiki.platform:xwiki-platform-mail-send-storage"
    +    }
    +)
     public class ForgotUsernameIT
     {
    +    private GreenMail mail;
    +
    +    @BeforeEach
    +    public void startMail(TestUtils setup, TestConfiguration testConfiguration)
    +    {
    +        this.mail = new GreenMail(ServerSetupTest.SMTP);
    +        this.mail.start();
    +
    +        configureEmail(setup, testConfiguration);
    +    }
    +
    +    @AfterEach
    +    public void stopMail(TestUtils setup, LogCaptureConfiguration logCaptureConfiguration)
    +    {
    +        if (this.mail != null) {
    +            this.mail.stop();
    +        }
    +
    +        restoreSettings(setup);
    +        logCaptureConfiguration.registerExcludes("CSRFToken: Secret token verification failed, token");
    +    }
    +
    +    private void configureEmail(TestUtils setup, TestConfiguration testConfiguration)
    +    {
    +        setup.updateObject("Mail", "MailConfig", "Mail.SendMailConfigClass", 0, "host",
    +            testConfiguration.getServletEngine().getHostIP(), "port", "3025", "sendWaitTime", "0");
    +    }
    +
    +    private void restoreSettings(TestUtils setup)
    +    {
    +        // Make sure we can restore the settings, so we log back with superadmin to finish the work
    +        setup.loginAsSuperAdmin();
    +
    +        // Remove the previous version that the setup has created.
    +        setup.deleteLatestVersion("Mail", "MailConfig");
    +    }
    +
    +    private Map<String, String> getMessageContent(MimeMessage message) throws Exception
    +    {
    +        Map<String, String> messageMap = new HashMap<>();
    +
    +        Address[] addresses = message.getAllRecipients();
    +        assertTrue(addresses.length == 1);
    +        messageMap.put("recipient", addresses[0].toString());
    +
    +        messageMap.put("subjectLine", message.getSubject());
    +
    +        Multipart mp = (Multipart) message.getContent();
    +
    +        BodyPart plain = getPart(mp, "text/plain");
    +        if (plain != null) {
    +            messageMap.put("textPart", IOUtils.toString(plain.getInputStream(), "UTF-8"));
    +        }
    +        BodyPart html = getPart(mp, "text/html");
    +        if (html != null) {
    +            messageMap.put("htmlPart", IOUtils.toString(html.getInputStream(), "UTF-8"));
    +        }
    +
    +        return messageMap;
    +    }
    +
    +    private BodyPart getPart(Multipart messageContent, String mimeType) throws Exception
    +    {
    +        for (int i = 0; i < messageContent.getCount(); i++) {
    +            BodyPart part = messageContent.getBodyPart(i);
    +
    +            if (part.isMimeType(mimeType)) {
    +                return part;
    +            }
    +
    +            if (part.isMimeType("multipart/related") || part.isMimeType("multipart/alternative")
    +                || part.isMimeType("multipart/mixed"))
    +            {
    +                BodyPart out = getPart((Multipart) part.getContent(), mimeType);
    +                if (out != null) {
    +                    return out;
    +                }
    +            }
    +        }
    +        return null;
    +    }
    +
         @Test
    -    public void retrieveUsername(TestUtils testUtils)
    +    public void retrieveUsername(TestUtils testUtils) throws Exception
         {
    -        String user = "realuser";
    -        String userMail = "realuser@host.org";
    +        // We create three users, two of them are sharing the same email
    +        String user1Login = "realuser1";
    +        String user1Email = "realuser@host.org";
    +
    +        String user2Login = "realuser2";
    +        String user2Email = "realuser@host.org";
    +
    +        String user3Login = "foo";
    +        String user3Email = "foo@host.org";
     
             // We need to login as superadmin to set the user email.
             testUtils.loginAsSuperAdmin();
    -        testUtils.createUser(user, "realuserpwd", testUtils.getURLToNonExistentPage(), "email", userMail);
    +        testUtils.createUser(user1Login, "realuserpwd", testUtils.getURLToNonExistentPage(), "email", user1Email);
    +        testUtils.createUser(user2Login, "realuserpwd", testUtils.getURLToNonExistentPage(), "email", user2Email);
    +        testUtils.createUser(user3Login, "realuserpwd", testUtils.getURLToNonExistentPage(), "email", user3Email);
     
             testUtils.forceGuestUser();
    +
    +        // check that when asking to retrieve username with a wrong email we don't get any information
    +        // if an user exists or not and no email is sent.
             ForgotUsernamePage forgotUsernamePage = ForgotUsernamePage.gotoPage();
    -        forgotUsernamePage.setEmail(userMail);
    +        forgotUsernamePage.setEmail("notexistant@xwiki.com");
             ForgotUsernameCompletePage forgotUsernameCompletePage = forgotUsernamePage.clickRetrieveUsername();
    -        assertFalse(forgotUsernameCompletePage.isAccountNotFound());
    -        assertTrue(forgotUsernameCompletePage.isUsernameRetrieved(user));
    +        assertTrue(forgotUsernameCompletePage.isForgotUsernameQuerySent());
    +
    +        // we are waiting 5 sec here just to be sure no mail is sent, maybe we could decrease the timeout value,
    +        // not sure.
    +        assertFalse(this.mail.waitForIncomingEmail(1));
     
             // Bypass the check that prevents to reload the current page
             testUtils.gotoPage(testUtils.getURLToNonExistentPage());
     
    -        // test that bad mail results in no results
    +        // test getting email for a forgot username request where the email is set in one account only
             forgotUsernamePage = ForgotUsernamePage.gotoPage();
    -        forgotUsernamePage.setEmail("bad_mail@evil.com");
    +        forgotUsernamePage.setEmail(user3Email);
             forgotUsernameCompletePage = forgotUsernamePage.clickRetrieveUsername();
    -        assertTrue(forgotUsernameCompletePage.isAccountNotFound());
    -        assertFalse(forgotUsernameCompletePage.isUsernameRetrieved(user));
    +        assertTrue(forgotUsernameCompletePage.isForgotUsernameQuerySent());
    +        assertTrue(this.mail.waitForIncomingEmail(1));
    +        MimeMessage[] receivedEmails = this.mail.getReceivedMessages();
    +        assertEquals(1, receivedEmails.length);
    +        MimeMessage receivedEmail = receivedEmails[0];
    +        assertTrue(receivedEmail.getSubject().contains("Forgot username on"));
    +        String receivedMailContent = getMessageContent(receivedEmail).get("textPart");
    +        assertTrue(receivedMailContent.contains(String.format("XWiki.%s", user3Login)));
    +
    +        // remove mails for last test
    +        this.mail.purgeEmailFromAllMailboxes();
     
             // Bypass the check that prevents to reload the current page
             testUtils.gotoPage(testUtils.getURLToNonExistentPage());
     
    -        // XWIKI-4920 test that the email is properly escaped
    +        // test getting email for a forgot username request where the email is set in two accounts
             forgotUsernamePage = ForgotUsernamePage.gotoPage();
    -        forgotUsernamePage.setEmail("a' synta\\'x error");
    +        forgotUsernamePage.setEmail(user1Email);
             forgotUsernameCompletePage = forgotUsernamePage.clickRetrieveUsername();
    -        assertTrue(forgotUsernameCompletePage.isAccountNotFound());
    -        assertFalse(forgotUsernameCompletePage.isUsernameRetrieved(user));
    +        assertTrue(forgotUsernameCompletePage.isForgotUsernameQuerySent());
    +        assertTrue(this.mail.waitForIncomingEmail(1));
    +        receivedEmails = this.mail.getReceivedMessages();
    +        assertEquals(1, receivedEmails.length);
    +        receivedEmail = receivedEmails[0];
    +        assertTrue(receivedEmail.getSubject().contains("Forgot username on"));
    +        receivedMailContent = getMessageContent(receivedEmail).get("textPart");
    +        assertTrue(receivedMailContent.contains(String.format("XWiki.%s", user1Login)));
    +        assertTrue(receivedMailContent.contains(String.format("XWiki.%s", user2Login)));
         }
     }
    
  • xwiki-platform-core/xwiki-platform-administration/xwiki-platform-administration-test/xwiki-platform-administration-test-pageobjects/src/main/java/org/xwiki/administration/test/po/ForgotUsernameCompletePage.java+34 0 modified
    @@ -21,6 +21,7 @@
     
     import org.openqa.selenium.By;
     import org.openqa.selenium.NoSuchElementException;
    +import org.xwiki.stability.Unstable;
     import org.xwiki.test.ui.po.ViewPage;
     
     /**
    @@ -31,6 +32,10 @@
      */
     public class ForgotUsernameCompletePage extends ViewPage
     {
    +    /**
    +     * @deprecated since 12.10.5 and 13.2RC1 this message is no longer displayed.
    +     */
    +    @Deprecated
         public boolean isUsernameRetrieved(String username)
         {
             try {
    @@ -42,8 +47,37 @@ public boolean isUsernameRetrieved(String username)
             }
         }
     
    +    /**
    +     * @deprecated since 12.10.5 and 13.2RC1 this message is no longer displayed.
    +     */
    +    @Deprecated
         public boolean isAccountNotFound()
         {
             return getContent().contains("No account is registered using this email address");
         }
    +
    +    /**
    +     * @return the text content of the message box.
    +     * @since 12.10.5
    +     * @since 13.2RC1
    +     */
    +    @Unstable
    +    public String getMessage()
    +    {
    +        return getContent();
    +    }
    +
    +    /**
    +     * @return {@code true} if the forgot username query was successfully sent (without any error).
    +     * @since 12.10.5
    +     * @since 13.2RC1
    +     */
    +    @Unstable
    +    public boolean isForgotUsernameQuerySent()
    +    {
    +        // If there is no form and we see an info box, then the request was sent.
    +        return !getDriver().hasElementWithoutWaiting(By.cssSelector("#forgotUsernameForm"))
    +            && getMessage().contains("If an account is registered with this email, "
    +            + "you will receive the account information on");
    +    }
     }
    
  • xwiki-platform-core/xwiki-platform-administration/xwiki-platform-administration-ui/src/main/resources/XWiki/ForgotUsernameMailContent.xml+141 0 added
    @@ -0,0 +1,141 @@
    +<?xml version="1.1" encoding="UTF-8"?>
    +
    +<!--
    + * 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.
    +-->
    +
    +<xwikidoc version="1.4" reference="XWiki.ForgotUsernameMailContent" locale="">
    +  <web>XWiki</web>
    +  <name>ForgotUsernameMailContent</name>
    +  <language/>
    +  <defaultLanguage/>
    +  <translation>0</translation>
    +  <creator>xwiki:XWiki.Admin</creator>
    +  <parent>WebHome</parent>
    +  <author>xwiki:XWiki.Admin</author>
    +  <contentAuthor>xwiki:XWiki.Admin</contentAuthor>
    +  <version>1.1</version>
    +  <title>Forgot Username email</title>
    +  <comment/>
    +  <minorEdit>false</minorEdit>
    +  <syntaxId>xwiki/2.0</syntaxId>
    +  <hidden>true</hidden>
    +  <content/>
    +  <object>
    +    <name>XWiki.ForgotUsernameMailContent</name>
    +    <number>0</number>
    +    <className>XWiki.Mail</className>
    +    <guid>5940d653-0e58-439f-ad1a-9e1afbecf9dc</guid>
    +    <class>
    +      <name>XWiki.Mail</name>
    +      <customClass/>
    +      <customMapping/>
    +      <defaultViewSheet/>
    +      <defaultEditSheet/>
    +      <defaultWeb/>
    +      <nameField/>
    +      <validationScript/>
    +      <html>
    +        <contenttype>PureText</contenttype>
    +        <disabled>0</disabled>
    +        <editor>PureText</editor>
    +        <name>html</name>
    +        <number>4</number>
    +        <prettyName>HTML</prettyName>
    +        <rows>15</rows>
    +        <size>80</size>
    +        <unmodifiable>0</unmodifiable>
    +        <classType>com.xpn.xwiki.objects.classes.TextAreaClass</classType>
    +      </html>
    +      <language>
    +        <disabled>0</disabled>
    +        <name>language</name>
    +        <number>2</number>
    +        <prettyName>Language</prettyName>
    +        <size>5</size>
    +        <unmodifiable>0</unmodifiable>
    +        <classType>com.xpn.xwiki.objects.classes.StringClass</classType>
    +      </language>
    +      <subject>
    +        <disabled>0</disabled>
    +        <name>subject</name>
    +        <number>1</number>
    +        <prettyName>Subject</prettyName>
    +        <size>40</size>
    +        <unmodifiable>0</unmodifiable>
    +        <classType>com.xpn.xwiki.objects.classes.StringClass</classType>
    +      </subject>
    +      <text>
    +        <contenttype>PureText</contenttype>
    +        <disabled>0</disabled>
    +        <editor>PureText</editor>
    +        <name>text</name>
    +        <number>3</number>
    +        <prettyName>Text</prettyName>
    +        <rows>15</rows>
    +        <size>80</size>
    +        <unmodifiable>0</unmodifiable>
    +        <classType>com.xpn.xwiki.objects.classes.TextAreaClass</classType>
    +      </text>
    +    </class>
    +    <property>
    +      <html>&lt;h2&gt;Hello,&lt;/h2&gt;
    +#set ($wikiurl = $xwiki.getURL($services.model.resolveDocument('', 'default', $doc.documentReference.extractReference('WIKI'))))
    +#set ($xwikiLoginURL = $xwiki.getURL('XWiki.XWikiLogin', 'login'))
    +#set ($wikiname = $request.serverName)
    +#set ($severalUsernames = ($usernames.size() &gt; 0))
    +&lt;p&gt;A forgot username request has been performed on &lt;a href="$wikiurl"&gt;$wikiname&lt;/a&gt;.
    +If you did not make the request, please ignore this message.&lt;/p&gt;
    +&lt;p&gt;We found the following username#if($severalUsernames)s#end related to this email address:
    +:&lt;br/&gt;
    +#if ($severalUsernames)
    +&lt;ul&gt;
    +#foreach ($username in $usernames)
    +  &lt;li&gt;$username&lt;/li&gt;
    +#end
    +&lt;/ul&gt;
    +#else
    +&lt;strong&gt;$usernames.get(0)&lt;/strong&gt;
    +#end
    +
    +&lt;p&gt;
    +You can login from this page: &lt;a href="$xwikiLoginURL"&gt;XWiki Login&lt;/a&gt;.
    +&lt;/p&gt;
    +</html>
    +    </property>
    +    <property>
    +      <language>en</language>
    +    </property>
    +    <property>
    +      <subject>Forgot username on ${request.getServerName()}</subject>
    +    </property>
    +    <property>
    +      <text>Hello,
    +
    +A forgot username request has been made on ${request.getServerName()}.
    +We found the following username(s) related to this email address:
    +
    +#foreach ($username in $usernames)
    +  $usernames
    +#end
    +
    +You can login with this username from this URL: $xwiki.getURL('XWiki.XWikiLogin', 'login').</text>
    +    </property>
    +  </object>
    +</xwikidoc>
    
  • xwiki-platform-core/xwiki-platform-administration/xwiki-platform-administration-ui/src/main/resources/XWiki/ForgotUsername.xml+54 12 modified
    @@ -54,22 +54,64 @@
       #if($results.size() == 0 &amp;&amp; ${xcontext.database} != ${xcontext.mainWikiName})
         #set($results = $query.setWiki("${xcontext.mainWikiName}").execute())
       #end
    -  #if($results.size() == 0)
    -    {{translation key="xe.admin.forgotUsername.error.noAccount"/}}
    +  #set ($emailError = false)
    +    #if($results.size() != 0)
    +      ## Send the email
    +      #set ($from = $services.mail.sender.configuration.fromAddress)
    +      #if ("$!from" == '')
    +        #set ($from = "no-reply@${request.serverName}")
    +      #end
    +      ## The mail template use $usernames to display the results.
    +      #set ($usernames = $results)
    +      #set ($mailTemplateReference = $services.model.createDocumentReference('', 'XWiki', 'ForgotUsernameMailContent'))
    +      #set ($mailParameters = {'from' : $from, 'to' : $email, 'language' : $xcontext.locale})
    +      #set ($message = $services.mail.sender.createMessage('template', $mailTemplateReference, $mailParameters))
    +      #set ($discard = $message.setType('Forgot Username'))
    +      #macro (displayError $text)
     
    -    [[{{translation key="xe.admin.forgotUsername.error.retry"/}}&gt;&gt;$doc.fullName]] | [[{{translation key="xe.admin.forgotUsername.login"/}}&gt;&gt;path:${xwiki.getURL('XWiki.XWikiLogin', 'login')}]]
    -  #elseif($results.size() == 1)
    -    $services.localization.render('xe.admin.forgotUsername.result', ["**${results.get(0).substring($results.get(0).indexOf('.')).substring(1)}**"])
    +        {{html}}
    +          &lt;div class="xwikirenderingerror" title="Click to get more details about the error" style="cursor: pointer;"&gt;
    +            $services.localization.render('xe.admin.forgotUsername.error.emailFailed')
    +          &lt;/div&gt;
    +          &lt;div class="xwikirenderingerrordescription hidden"&gt;
    +            &lt;pre&gt;${text}&lt;/pre&gt;
    +          &lt;/div&gt;
    +        {{/html}}
     
    -    [[{{translation key="xe.admin.forgotUsername.login"/}}&gt;&gt;path:${xwiki.getURL('XWiki.XWikiLogin', 'login')}]]
    -  #else
    -    {{translation key="xe.admin.forgotUsername.multipleResults"/}}
    -    #foreach($item in $results)
    -      * **${item.substring($item.indexOf('.')).substring(1)}**
    +        #set ($emailError = true)
    +      #end
    +      ## Check for an error constructing the message!
    +      #if ($services.mail.sender.lastError)
    +          #displayError($exceptiontool.getStackTrace($services.mail.sender.lastError))
    +      #else
    +          ## Send the message and wait for it to be sent or for any error to be raised.
    +          #set ($mailResult = $services.mail.sender.send([$message], 'database'))
    +          ## Check for errors during the send
    +          #if ($services.mail.sender.lastError)
    +              #displayError($exceptiontool.getStackTrace($services.mail.sender.lastError))
    +          #else
    +              #set ($failedMailStatuses = $mailResult.statusResult.getAllErrors())
    +              #if ($failedMailStatuses.hasNext())
    +                  #set ($mailStatus = $failedMailStatuses.next())
    +                  #displayError($mailStatus.errorDescription)
    +              #end
    +          #end
    +      #end
         #end
    +    ## We always display a success message even if there's no user found to avoid disclosing information
    +    ## about the users registered on the wiki.
    +    #if (!$emailError)
    +      {{success}}
    +        $services.localization.render('xe.admin.forgotUsername.emailSent', ["$email"])
     
    -    [[{{translation key="xe.admin.forgotUsername.login"/}}&gt;&gt;path:${xwiki.getURL('XWiki.XWikiLogin', 'login')}]]
    -  #end
    +        {{html}}
    +        &lt;div&gt;
    +          &lt;a href="$xwiki.getURL('XWiki.XWikiLogin', 'login')"&gt;$services.localization.render('xe.admin.forgotUsername.login')&lt;/a&gt;
    +        &lt;/div&gt;
    +        {{/html}}
    +
    +      {{/success}}
    +    #end
     #end
     {{/velocity}}</content>
       <object>
    
  • xwiki-platform-core/xwiki-platform-oldcore/src/main/resources/ApplicationResources.properties+10 4 modified
    @@ -2436,16 +2436,14 @@ xe.admin.skin.testskin=Test this skin
     
     ### Username recovery
     xe.admin.forgotUsername.loginMessage=Forgot your username?
    -
     xe.admin.forgotUsername.title=Forgot your username?
     xe.admin.forgotUsername.instructions=Please enter the email address you provided when creating your account.
     xe.admin.forgotUsername.email.label=Email address
     xe.admin.forgotUsername.submit=Retrieve username
    -xe.admin.forgotUsername.result=Your username is: {0}
    -xe.admin.forgotUsername.multipleResults=The following usernames are registered with this email address:
     xe.admin.forgotUsername.login=Login \u00BB
    -xe.admin.forgotUsername.error.noAccount=No account is registered using this email address.
     xe.admin.forgotUsername.error.retry=\u00AB Try again using another email address
    +xe.admin.forgotUsername.error.emailFailed=An unknown problem occurred while sending the forgot username email.
    +xe.admin.forgotUsername.emailSent=If an account is registered with this email, you will receive the account information on {0}.
     
     ### Password reset
     xe.admin.passwordReset.loginMessage=Forgot your password?
    @@ -5483,6 +5481,14 @@ core.editors.object.delete.confirm=Are you sure you want to delete this object?
     core.viewers.jump.dialog.invalidNameError=Invalid page name. Valid names have the following format: Space.Page
     core.viewers.jump.suggest.noResults=No pages found
     
    +#######################################
    +## until 12.10.5, 13.2RC1
    +#######################################
    +
    +xe.admin.forgotUsername.result=Your username is: {0}
    +xe.admin.forgotUsername.multipleResults=The following usernames are registered with this email address:
    +xe.admin.forgotUsername.error.noAccount=No account is registered using this email address.
    +
     ## Used to indicate where deprecated keys end
     #@deprecatedend
     
    

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

7

News mentions

0

No linked articles in our index yet.