CVE-2026-59281
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Spring Framework is a widely used application framework for the Java platform that provides the core programming and configuration model for modern Java enterprise applications, including the Spring MVC servlet web stack and the Spring WebFlux reactive web stack. Both stacks bind request parameters onto Java objects and collect binding and validation failures in an Errors instance, which views then render to show users what went wrong with a submitted form. When HTML escaping is enabled, the framework hands views an EscapedErrors wrapper from the spring-web module, which is meant to HTML-escape every error message and rejected value before it reaches the page so that templates can print them safely.
A cross-site scripting vulnerability (CVE-2026-59281) has been identified in EscapedErrors, which allows attackers to inject arbitrary HTML and JavaScript into a page rendered by a Spring MVC or Spring WebFlux application, because the wrapper's no-argument getFieldErrors() and getFieldError() accessors return the underlying field errors without escaping them. A view that obtains a data-binding Errors instance with HTML escaping enabled and then renders field errors through either of those two accessors writes attacker-controlled markup into the response, resulting in a reflected cross-site scripting vulnerability.
Per OWASP: Cross-Site Scripting (XSS) attacks are a type of injection, in which malicious scripts are injected into otherwise benign and trusted websites. XSS attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, to a different end user. Flaws that allow these attacks to succeed are quite widespread and occur anywhere a web application uses input from a user within the output it generates without validating or encoding it.
The advisory rates this vulnerability Medium severity with the CVSS v3.1 vector AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:L/A:N, which corresponds to a base score of 5.9. The attack vector is Network because the malicious value arrives in an ordinary HTTP request, the attack complexity is High because the application must have HTML escaping enabled and render field errors through the two specific no-argument accessors, user interaction is Required because a victim must load the attacker-crafted request, and the Confidentiality impact is High because a script running in the victim's browser can read session cookies, tokens, and other data the browser holds for the site.
This issue affects Spring Framework <=5.2.25, >=5.3.0 <=5.3.49, >=6.0.0 <=6.0.30, >=6.1.0 <=6.1.28, >=6.2.0 <=6.2.19, and >=7.0.0 <=7.0.8, including the End-of-Life 4.3.x, 5.3.x, 6.1.x, and 6.2.x lines supported by NES for Spring Framework.
Details
Module Info
- Product: Spring Framework
- Affected packages:
org.springframework:spring-web - Affected versions: <=5.2.25, >=5.3.0 <=5.3.49, >=6.0.0 <=6.0.30, >=6.1.0 <=6.1.28, >=6.2.0 <=6.2.19, >=7.0.0 <=7.0.8
- GitHub repository: https://github.com/spring-projects/spring-framework
- Published packages: https://central.sonatype.com/artifact/org.springframework/spring-web
- Package manager: Maven
- Fixed in:
- NES for Spring Framework nes-v4.3.40, nes-v5.3.54, nes-v6.1.30, and nes-v6.2.21
- Spring Framework 7.0.9 (OSS)
Vulnerability Info
This Medium-severity vulnerability is found in the spring-web package in multiple versions of Spring Framework. org.springframework.web.bind.EscapedErrors is a decorator around an Errors instance whose contract is to HTML-escape every message and rejected value it hands out, so that a view can print binding and validation errors without escaping them itself. The wrapper is created by the RequestContext classes of Spring MVC and Spring WebFlux whenever a view asks for an Errors object with HTML escaping enabled, either because the application sets the defaultHtmlEscape servlet context parameter, because a template calls getErrors(name, true) directly, or because a JSP uses the <spring:hasBindErrors> tag with htmlEscape="true".
Most of the wrapper's accessors honour that contract: getAllErrors(), getGlobalErrors(), getGlobalError(), getFieldErrors(String field), and getFieldError(String field) all route the underlying errors through private helpers that HTML-escape the default message and, for a FieldError, the rejected value, returning a freshly built escaped copy. The two no-argument field-error accessors, however, return the source's FieldError objects untouched:
@Override
public List<FieldError> getFieldErrors() {
return this.source.getFieldErrors();
}
@Override
public FieldError getFieldError() {
return this.source.getFieldError();
}
A FieldError produced by data binding carries the raw submitted value as its rejectedValue, and a binding failure such as a type mismatch always does so. An attacker therefore crafts a request in which a form field contains markup such as <script>alert(1)</script>. Binding or validation rejects the field and records the raw input on the resulting FieldError. A view that trusts the escaped Errors instance and iterates the aggregate field errors, for example a JSP loop over ${errors.fieldErrors} inside <spring:hasBindErrors> that prints each error's rejectedValue or defaultMessage, or the equivalent in a FreeMarker or Groovy template, receives the unescaped objects and writes the attacker's markup straight into the HTML response. When a victim loads the attacker-crafted request, the injected script runs in the victim's browser in the context of the application. Views that render errors through the per-field accessors, through getAllErrors(), or through the <form:errors> tag are not exposed, because those paths escape independently; only views that read field errors through the two no-argument accessors on an escaping-enabled Errors instance are affected.
This vulnerability was introduced in 2006 with Spring Framework 2.0.
Mitigation
Only recent versions of Spring Framework receive community support. The 4.3.x, 5.3.x, 6.1.x, and 6.2.x lines are End-of-Life and will not receive public updates to address this issue, so there is no publicly available fix for those lines other than through a commercial support partner.
Applications that cannot upgrade immediately can reduce their exposure by rendering field errors through the per-field getFieldErrors(String field) and getFieldError(String field) accessors or through getAllErrors(), which are escaped correctly, or by explicitly HTML-escaping the rejectedValue and defaultMessage of each field error in the template rather than relying on the wrapper to do so.
Users of the affected components should apply one of the following mitigations:
- Upgrade to a currently supported version of Spring Framework. The open-source fix ships in Spring Framework 7.0.9 on the 7.0.x line.
- Leverage a commercial support partner like HeroDevs for post-EOL security support, which provides the fix for the 4.3.x, 5.3.x, 6.1.x, and 6.2.x lines in nes-v4.3.40, nes-v5.3.54, nes-v6.1.30, and nes-v6.2.21.
Credits
- No public finder credit is listed in the advisory sources checked for this entry.