Introduction
A single call to String.equals() in Spring Boot's DevTools remote access manager has been leaking timing information that allows adjacent network attackers to reconstruct the remote secret character by character. Once that secret is recovered, the attacker can push arbitrary class files through the DevTools live reload mechanism, turning a subtle cryptographic weakness into full remote code execution.
CVE-2026-40972 carries a CVSS v3.1 score of 7.5 and affects Spring Boot versions across five release trains, from the legacy 2.7.x line through the current 4.0.x series. Given Spring Boot's dominant position in enterprise Java development, the blast radius of this vulnerability is significant for any organization that has inadvertently left DevTools remote support enabled outside of a tightly controlled development environment.
Technical Information
Root Cause: Non-Constant-Time Secret Comparison (CWE-208)
The vulnerability exists in the HttpHeaderAccessManager class, located in the spring-boot-devtools module under org.springframework.boot.devtools.remote.server. This class is responsible for gating access to the remote DevTools endpoint by validating a secret provided in an HTTP header against an expected value configured via the spring.devtools.remote.secret property.
The original implementation stored the expected secret as a String and compared it against the incoming header value using Java's standard String.equals() method. This is the classic timing oracle pattern described by CWE-208 (Observable Timing Discrepancy). String.equals() short-circuits: it returns false as soon as it encounters the first mismatched character. This means a request carrying a secret whose first N characters match the expected value will take measurably longer to reject than a request that differs at position 0.
Attack Flow
The exploitation path proceeds as follows:
-
Prerequisite: The target Spring Boot application has DevTools remote support enabled, meaning the
spring.devtools.remote.secretproperty is set. The attacker must be on the same network (adjacent network access, per the CVSS vector AV:A). -
Timing oracle probing: The attacker sends repeated HTTP requests to the DevTools remote endpoint, varying the secret header value one character at a time. By collecting statistical measurements of response times, the attacker identifies which character value at each position produces a slightly longer comparison time, indicating a match.
-
Secret reconstruction: Character by character, the attacker builds up the full secret. While network jitter introduces noise (reflected in the AC:H rating), a patient attacker with sufficient samples can filter out the signal. On a low latency local network, this becomes considerably more practical.
-
Class upload and code execution: With the recovered secret, the attacker authenticates to the DevTools remote endpoint as a legitimate IDE client. The DevTools protocol allows uploading changed classes, which the server side live reload mechanism processes and loads into the running application. The attacker uploads a malicious class, achieving remote code execution.
CVSS Breakdown
The full CVSS v3.1 vector is AV:A/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H, which breaks down as:
| Metric | Value | Practical Meaning |
|---|---|---|
| Attack Vector | Adjacent (A) | Attacker must be on the same network as the target application |
| Attack Complexity | High (H) | Timing attacks require precise measurements and favorable network conditions |
| Privileges Required | None (N) | No prior authentication is needed to initiate the timing attack |
| User Interaction | None (N) | The exploit runs entirely without victim participation |
| Impact (C, I, A) | High (H) | Complete compromise of confidentiality, integrity, and availability via RCE |
The high attack complexity is the primary factor keeping this from a critical rating, but on a quiet local network segment the timing signal can be quite clear.
Patch Information
The Spring Boot team addressed CVE-2026-40972 with a precise, surgical patch authored by Andy Wilkinson and committed on April 23, 2026 (commit 4b0862cc). The commit message captures the intent directly: "Use constant-time comparison for remote DevTools secret."
The fix targets a single file: HttpHeaderAccessManager.java. The patch is compact (7 additions, 3 deletions) but addresses the root cause precisely:
+import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; - private final String expectedSecret; + private final byte[] expectedSecret; public HttpHeaderAccessManager(String headerName, String expectedSecret) { ... - this.expectedSecret = expectedSecret; + this.expectedSecret = expectedSecret.getBytes(StandardCharsets.UTF_8); } @Override public boolean isAllowed(ServerHttpRequest request) { String providedSecret = request.getHeaders().getFirst(this.headerName); - return this.expectedSecret.equals(providedSecret); + return (providedSecret != null) + && MessageDigest.isEqual(providedSecret.getBytes(StandardCharsets.UTF_8), this.expectedSecret); }
Two key changes are worth understanding:
-
Storage format change: The expected secret is now stored as a
byte[](converted viaStandardCharsets.UTF_8) rather than as aString. This is a prerequisite for using the constant-time comparison API. -
Constant-time comparison: The old
String.equals()call is replaced withMessageDigest.isEqual(). This method, part of thejava.securitypackage, is specifically designed for comparing cryptographic values. It always iterates over the full length of both byte arrays regardless of where differences occur, making the comparison time independent of the secret's content. A null check (providedSecret != null) was also added as a guard, sinceString.equals()inherently handled null safely (by returningfalse), whereas callinggetBytes()on a null reference would throw aNullPointerException.
The fix was originally tracked as issue #50169 (milestone 3.5.14) and forward-ported to the 4.0.x branch as issue #50176 (milestone 4.0.6).
Fixed Versions
| Affected Version Range | Fixed Version | Availability |
|---|---|---|
| 4.0.0 to 4.0.5 | 4.0.6 | OSS |
| 3.5.0 to 3.5.13 | 3.5.14 | OSS |
| 3.4.0 to 3.4.15 | 3.4.16 | Enterprise Support Only |
| 3.3.0 to 3.3.18 | 3.3.19 | Enterprise Support Only |
| 2.7.0 to 2.7.32 | 2.7.33 | Enterprise Support Only |
The two OSS available versions (4.0.6 and 3.5.14) both list "Remote DevTools performs comparison incorrectly" in their release notes. Older supported branches received the same fix but are only available through Spring Enterprise Support.
The vendor states that no further mitigation steps are necessary once the patch is applied. For environments where immediate patching is not possible, DevTools remote support should be disabled entirely, especially in production, where it should never be enabled in the first place.
Affected Systems and Versions
The vulnerability affects any Spring Boot application that has DevTools remote support enabled (i.e., the spring.devtools.remote.secret property is set) across the following version ranges:
- Spring Boot 4.0.0 through 4.0.5 (fixed in 4.0.6)
- Spring Boot 3.5.0 through 3.5.13 (fixed in 3.5.14)
- Spring Boot 3.4.0 through 3.4.15 (fixed in 3.4.16)
- Spring Boot 3.3.0 through 3.3.18 (fixed in 3.3.19)
- Spring Boot 2.7.0 through 2.7.32 (fixed in 2.7.33)
Versions that are no longer supported by the vendor are also affected per the vendor advisory. Organizations running unsupported versions must upgrade to a supported release train.
The vulnerable component is specifically the remote DevTools server side endpoint (HttpHeaderAccessManager in spring-boot-devtools). Applications that do not set spring.devtools.remote.secret and do not include DevTools in their deployed artifacts are not affected.
Vendor Security History
The April 23, 2026 Spring Boot release bundled fixes for nine distinct CVEs, indicating an active period of security review. Notable vulnerabilities addressed alongside CVE-2026-40972 include:
| CVE ID | Severity | Description |
|---|---|---|
| CVE-2026-40976 | Critical | Default security filter chain has no authorization rule with Actuator but without Health |
| CVE-2026-40972 | High | DevTools remote secret comparison is vulnerable to timing attacks |
| CVE-2026-40973 | High | Predictable temp directory accepted without ownership verification |
| CVE-2026-40974 | Medium | Cassandra SSL auto configuration disables TLS hostname verification |
This coordinated release allowed organizations to address multiple security flaws in a single maintenance window. The vendor's restriction of fixes for older branches (3.4.x, 3.3.x, 2.7.x) to Enterprise Support Only is worth noting for organizations that rely on open source releases, as it effectively requires a major version upgrade to maintain security without a commercial support agreement.
References
- NVD: CVE-2026-40972
- CVE Record: CVE-2026-40972
- Spring Security Advisory: CVE-2026-40972
- Spring Blog: Spring Boot 3.5.14 Available Now
- GitHub Release: Spring Boot v3.5.14
- GitHub Release: Spring Boot v4.0.6
- GitHub Issue #50169: Fix for 3.5.14
- GitHub Issue #50176: Fix for 4.0.6
- GitHub Commit 4b0862cc: Use constant-time comparison for remote DevTools secret
- Spring Boot DevTools Documentation
- Heise: VMware Tanzu Spring Boot Attackers Can Access Endpoints
- SecurityOnline: Spring Boot Vulnerability CVE-2026-40976
- Spring Boot Project Page



