WW-5635 Avoid logging sensitive token values in TokenHelper (#1738)

* Avoid logging sensitive token values in TokenHelper

Redact form and session token values from WARN-level log output
in TokenHelper.validToken() and update corresponding i18n message
properties. Detailed diagnostics moved to DEBUG level with
sanitized input.

* Update struts-messages.properties

* Update invalid token error message for clarity

* Update struts-messages_da.properties

* Update struts-messages_de.properties

* Update Polish translation for invalid token message

* Update invalid token message in Portuguese properties

* Improve token mismatch warning logging

Updated warning message to include the form token in the log.

* Update struts-messages.properties

* Update invalid token message format in properties file

* Update invalid token message for clarity

* Update struts-messages_de.properties

* Update struts-messages_pl.properties

* Update invalid token message format in properties file

* Update TokenHelper.java

* Refactor token mismatch logging for development mode
This commit is contained in:
Arun
2026-06-14 22:38:39 +05:30
committed by GitHub
parent 8f9b4b8a90
commit cc3ebc3c1f
7 changed files with 15 additions and 8 deletions
@@ -18,6 +18,7 @@
*/
package org.apache.struts2.util;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.ActionContext;
import org.apache.struts2.text.LocalizedTextProvider;
import org.apache.logging.log4j.LogManager;
@@ -29,6 +30,7 @@ import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Map;
import java.util.Random;
import static org.apache.commons.lang3.StringUtils.normalizeSpace;
/**
* TokenHelper
@@ -186,10 +188,15 @@ public class TokenHelper {
if (!token.equals(sessionToken)) {
if (LOG.isWarnEnabled()) {
LocalizedTextProvider localizedTextProvider = ActionContext.getContext().getContainer().getInstance(LocalizedTextProvider.class);
LOG.warn(localizedTextProvider.findText(TokenHelper.class, "struts.internal.invalid.token", ActionContext.getContext().getLocale(), "Form token {0} does not match the session token {1}.", new Object[]{
token, sessionToken
LOG.warn(localizedTextProvider.findText(TokenHelper.class, "struts.internal.invalid.token", ActionContext.getContext().getLocale(), "Form token {0} does not match the expected session token.", new Object[]{
normalizeSpace(token)
}));
}
Dispatcher dispatcher = Dispatcher.getInstance();
if (dispatcher != null && dispatcher.isDevMode()) {
LOG.warn("Token mismatch detail - token name [{}], form token [{}], session token [{}]",
normalizeSpace(tokenName), normalizeSpace(token), sessionToken);
}
return false;
}
@@ -20,7 +20,7 @@
# See https://issues.apache.org/jira/browse/WW-4195 for more details!
struts.messages.invalid.token=The form has already been processed or no token was supplied, please try again.
struts.internal.invalid.token=Form token {0} does not match the session token {1}.
struts.internal.invalid.token=Form token {0} does not match the expected session token.
struts.messages.bypass.request=Bypassing {0}/{1}
struts.messages.current.file=File {0} {1} {2} {3}
@@ -17,7 +17,7 @@
# under the License.
#
struts.messages.invalid.token=Denne form er allerede blevet behandlet eller der mangler en token, venligst pr\u00F8v igen.
struts.internal.invalid.token=Form token {0} passer ikke med den token som findes i session {1}.
struts.internal.invalid.token=Form token {0} passer ikke med den forventede session-token.
struts.messages.bypass.request=Springer over {0}/{1}
struts.messages.current.file=Fil {0} {1} {2} {3}
@@ -17,7 +17,7 @@
# under the License.
#
struts.messages.invalid.token=Das Formular wurde bereits verarbeitet oder es wurde kein Token angegeben, bitte versuchen Sie es erneut.
struts.internal.invalid.token=Das Formular Token {0} stimmt nicht mit dem Session Token {1} \u00FCberein.
struts.internal.invalid.token=Das Formular-Token {0} stimmt nicht mit dem erwarteten Session-Token \u00FCberein.
struts.messages.bypass.request=\u00DCberspringe {0}/{1}
struts.messages.current.file=Datei {0} {1} {2} {3}
@@ -21,7 +21,7 @@
# See https://issues.apache.org/jira/browse/WW-4195 for more details!
struts.messages.invalid.token=The form has already been processed or no token was supplied, please try again.
struts.internal.invalid.token=Form token {0} does not match the session token {1}.
struts.internal.invalid.token=Form token {0} does not match the expected session token.
struts.messages.bypass.request=Bypassing {0}/{1}
struts.messages.current.file=File {0} {1} {2} {3}
@@ -17,7 +17,7 @@
# under the License.
#
struts.messages.invalid.token=Formularz zosta\u0142 ju\u017C przetworzony lub nie za\u0142\u0105czono tokena, spr\u00F3buj ponownie.
struts.internal.invalid.token=Token formularza {0} nie pasuje do tokena sesji {1}.
struts.internal.invalid.token=Token formularza {0} nie pasuje do oczekiwanego tokena sesji.
struts.messages.bypass.request=Omijanie {0}/{1}
struts.messages.current.file=Plik {0} {1} {2} {3}
@@ -17,7 +17,7 @@
# under the License.
#
struts.messages.invalid.token=O formulario j\u00E1 foi processado ou nenhum token foi gerado, por favor tente novamente.
struts.internal.invalid.token=O token do formul\u00E1rio {0} \u00E9 diferente do token de sess\u00E3o {1}.
struts.internal.invalid.token=O token do formul\u00E1rio {0} \u00E9 diferente do token de sess\u00E3o esperado.
struts.messages.bypass.request=Ignorando {0}/ {1}
struts.messages.current.file=Arquivo {0} {1} {2} {3}