CVE-2026-104714
Patch Available.
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Apache Struts is a popular open-source web application framework for developing Java EE web applications. Struts renders localized messages through an application-wide text provider, which formats each message from the application's resource bundles with Java's MessageFormat.
An information exposure vulnerability (CVE-2026-104714) has been identified in the Apache Struts localized text provider, which allows one user's date or time value to appear in another user's response when requests are served concurrently. The same race can also make message rendering fail and surface as a server error.
Per OWASP: Access control enforces policy such that users cannot act outside of their intended permissions. Failures typically lead to unauthorized information disclosure, modification, or destruction of all data or performing a business function outside the user's limits.
This issue affects multiple versions of Apache Struts 2.
Details
Module Info
- Product: Apache Struts 2
- Affected packages:
org.apache.struts:struts2-core - Affected versions: >=2.0.0 <=2.3.37, >=2.5.0 <=2.5.33, >=6.0.0 <=6.11.0, >=7.0.0 <=7.3.0
- GitHub repository: https://github.com/apache/struts
- Published packages: https://central.sonatype.com/artifact/org.apache.struts/struts2-core
- Package manager: Maven
- Fixed in:
- OSS Apache Struts 6.12.0, 7.4.0
- NES for Apache Struts nes-v2.5.41
Vulnerability Info
This High-severity vulnerability is found in the org.apache.struts:struts2-core package in multiple versions of Apache Struts 2. AbstractLocalizedTextProvider caches a MessageFormat for each message pattern and locale in an application-wide map, and buildMessageFormat returns that cached instance itself to every caller:
private final ConcurrentMap<MessageFormatKey, MessageFormat> messageFormats = new ConcurrentHashMap<>();
protected MessageFormat buildMessageFormat(String pattern, Locale locale) {
MessageFormatKey key = new MessageFormatKey(pattern, locale);
MessageFormat format = messageFormats.get(key);
if (format == null) {
format = new MessageFormat(pattern);
format.setLocale(locale);
format.applyPattern(pattern);
messageFormats.put(key, format);
}
return format;
}
Every message lookup path (findDefaultText, findText, getDefaultMessage and getMessage) then passes that instance to formatWithNullDetection, which calls mf.format(args) on the shared instance. MessageFormat is not thread-safe. When a pattern formats a date or time argument (for example {0,date,short}), the format delegates to a DateFormat subformat that keeps a mutable Calendar for the value being formatted. Two requests rendering the same localized message at the same moment therefore write their arguments into the same Calendar. One request can render the other user's date or time value, or formatting can throw and surface as a server error. No crafted input is needed, because ordinary concurrent traffic is enough. The exposure depends on the application's own resource bundles: messages that format no date or time argument are not affected, and no message shipped with Struts formats one.
Mitigation
Only recent versions of Apache Struts are community-supported. Older lines are End-of-Life and will not receive any updates to address this issue.
Where a localized message formats a date or time argument, format the value in application code before passing it to the message, and use a message that interpolates the already-formatted value without a date or time format type. This removes the exposure for that message.
Users of the affected components should apply one of the following mitigations:
- Upgrade affected applications to a supported version of Apache Struts.
- Leverage a commercial support partner like HeroDevs for post-EOL security support.
Credits
- n0mi1k (finder)