CVE-2026-40972
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Spring Boot is an open-source framework from the Spring team that simplifies building production-grade Java applications by providing opinionated auto-configuration, embedded servlet containers, and convention-based starters. Spring Boot DevTools is a developer-productivity module that, when remote support is enabled via spring.devtools.remote.secret, exposes an HTTP dispatcher for live class reloading and JDWP-style tunneling from a developer workstation to a running remote application.
A high-severity vulnerability (CVE-2026-40972) has been identified in the DevTools remote-access guard, HttpHeaderAccessManager. The class compared the secret header supplied by the caller against the configured secret using java.lang.String.equals, which short-circuits on the first mismatching character. A network-adjacent attacker can measure per-request response times to recover the secret one byte at a time. Once the secret is known, the attacker can authenticate to the DevTools remote endpoint, upload attacker-controlled class bytes through the remote restart server, and achieve remote code execution in the application JVM.
Per OWASP: "Processing timing may give/leak information on what is being done in the application/system background processes. It is possible that attackers can gather information on an application by monitoring the time it takes to complete a task or give a response." Authentication and secret comparison primitives are expected to execute in constant time so that this timing channel is closed.
This issue affects Spring Boot >=1.3.0 <=2.7.32, >=3.3.0 <=3.3.18, >=3.4.0 <=3.4.15, >=3.5.0 <=3.5.13, and >=4.0.0 <=4.0.5.
Details
Module Info
- Product: Spring Boot
- Affected packages: spring-boot-devtools
- Affected versions: >=1.3.0 <=2.7.32, >=3.3.0 <=3.3.18, >=3.4.0 <=3.4.15, >=3.5.0 <=3.5.13, >=4.0.0 <=4.0.5
- GitHub repository: https://github.com/spring-projects/spring-boot
- Published packages: https://central.sonatype.com/artifact/org.springframework.boot/spring-boot-devtools
- Package manager: maven
- Fixed in:
- NES for Spring Boot 1.5.x, 2.5.x, 2.7.x, 3.2.x, 3.3.x, 3.4.x
- OSS Spring Boot 3.5.14, 4.0.6
Vulnerability Info
Spring Boot DevTools can be configured to accept remote connections from a developer workstation by setting spring.devtools.remote.secret on the running application. When this property is set, RemoteDevToolsAutoConfiguration registers a DispatcherFilter that routes requests under the remote context path (default /.~~spring-boot!~) to DevTools handlers, including HttpRestartServer (remote class upload and live restart) and HttpTunnelServer (reverse tunnel). Every request to these handlers is gated by a single AccessManager bean, HttpHeaderAccessManager, which compares the value of a configurable HTTP header (spring.devtools.remote.secret-header-name, default X-AUTH-TOKEN) against the configured secret.
In the vulnerable implementation, HttpHeaderAccessManager held the expected secret as a String and performed the comparison with String.equals:
public class HttpHeaderAccessManager implements AccessManager {
private final String headerName;
private final String expectedSecret;
public HttpHeaderAccessManager(String headerName, String expectedSecret) {
Assert.hasLength(headerName, "'headerName' must not be empty");
Assert.hasLength(expectedSecret, "'expectedSecret' must not be empty");
this.headerName = headerName;
this.expectedSecret = expectedSecret;
}
@Override
public boolean isAllowed(ServerHttpRequest request) {
String providedSecret = request.getHeaders().getFirst(this.headerName);
return this.expectedSecret.equals(providedSecret);
}
}
String.equals walks the two strings character by character and returns false at the first mismatch. The time spent inside isAllowed therefore scales with the length of the matching prefix between the attacker's guess and the real secret. An attacker on the same network as the remote application can submit repeated guesses and measure response times with sub-millisecond precision; by keeping the guess that took marginally longer, the attacker recovers the secret one byte at a time. The CVSS vector AV:A/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H reflects that the attack requires network adjacency and careful timing measurement (high attack complexity) but no prior credentials or user interaction.
Once the secret is recovered, the attacker is an authenticated DevTools remote client. Posting to the remote restart endpoint with attacker-supplied class bytes causes the DevTools restart class loader to load those classes into the live JVM on the next restart cycle, yielding code execution in the remote application as described by the advisory: "this could result in the attacker determining the secret and uploading changed classes, thereby achieving remote code execution in the remote application."
The fix converts the expected secret to a UTF-8 byte array at construction time and replaces String.equals with java.security.MessageDigest.isEqual, which is documented and implemented to run in constant time regardless of where the first mismatch occurs.
MessageDigest.isEqual(byte[], byte[]) iterates over the full length of the shorter array, XOR-accumulates each byte-pair difference into a single integer, and only compares that accumulator to zero at the end. The execution time no longer depends on the position of the first mismatch, closing the timing oracle. An explicit null-guard on providedSecret was added to preserve the previous behavior when the header is missing.
HttpHeaderAccessManager has existed in essentially this form since Spring Boot 1.3.0, which introduced the remote DevTools feature in June 2015 . The vulnerable expectedSecret.equals(providedSecret) line was present from that first commit and remained unchanged until the April 2026 patch, so every Spring Boot release from 1.3.0 through the ranges listed above that enables remote DevTools is affected.
Mitigation
Only recent versions of Spring Boot receive community support and updates. See Spring Boot’s project support page for the current OSS support policy. We recommend the following courses of action:
- Upgrade to a currently-supported Spring Boot release (3.5.14 or 4.0.6 or later) that contains the constant-time comparison fix.
- Adopt HeroDevs Never-Ending Support for Spring Boot to receive the backported HttpHeaderAccessManager fix on 1.5.x, 2.5.x, 2.7.x, 3.2.x, 3.3.x, and 3.4.x while planning a longer-term upgrade. See NES for Spring for details.
Credits
No external finder is credited in the upstream advisory as of April 24, 2026.