Introduction
Spring Boot's ApplicationTemp class uses a predictable temporary directory. A local attacker can hijack that location, which holds persisted sessions and other sensitive temporary data, and this can lead to authenticated session theft or arbitrary code execution. For organizations running Spring Boot applications in multi-tenant environments or on shared hosts, a common framework convenience becomes a local privilege escalation path.
Spring Boot is the most widely adopted Java framework for building web applications and microservices. Because it runs across so many enterprise environments, CVE-2026-40973 has a large blast radius, even though exploitation requires local access. The CVSS base score of 7.0 (HIGH) reflects high confidentiality, integrity, and availability impact, weighed against two constraints: the attacker needs local access, and attack complexity is high.
Technical Information
Root Cause: Predictable Directory Names Without Ownership Verification
The vulnerability is in the ApplicationTemp class, which gives each Spring Boot application a dedicated temporary directory. According to the Spring Boot API documentation, different Spring Boot applications get different temporary locations, but restarting a given application yields the exact same location. That determinism is the first ingredient of the vulnerability.
The second ingredient is that nothing validated an existing directory at that path. Before the fix, the code called Files.exists(path) to check whether the temporary directory already existed. That call transparently follows symbolic links, so an attacker who placed a symlink at the predictable path could redirect the application's temporary storage to a location they control, and the application would not notice.
The code did not verify ownership either. If another user had already created the directory, the application used it without checking who owned it.
Attack Flow
Exploiting CVE-2026-40973 takes four steps:
-
An attacker with local access to the host works out the temporary directory path that a target Spring Boot application will use.
ApplicationTempgenerates the same path for the same application across restarts, so this is straightforward. -
Before the application starts (or restarts), the attacker either creates a directory at that path under their own user account or plants a symbolic link there that points to a directory they control.
-
The attacker waits for the application to restart. On startup, the application finds the directory (or symlink) already in place. The old code's
Files.exists(path)call follows the symlink, sees a valid directory, and moves on without creating a new one. -
If the application has
server.servlet.session.persistentset totrue, it writes session data to this compromised directory and reads it back across restarts. The attacker then has two options:- Session hijacking: Read the stored session information and impersonate authenticated users.
- Code execution via deserialization: Place a malicious gadget chain in the session data. When the application deserializes that data on restart, the attacker's code runs with the application user's privileges.
CWE Classification
The vulnerability falls under CWE-377: Insecure Temporary File, which covers temporary files created in a way that lets local attackers interfere with their intended use.
Patch Information
The Spring Boot team released the official patch on April 23, 2026. Andy Wilkinson authored and committed it. The fix was first developed on the 3.5.x branch (issue #50170, commit 5ceb1a2) and then forward-ported to the 4.0.x branch (issue #50178, merge commit 8e013b6). It changes one production file, ApplicationTemp.java (57 additions, 4 deletions), and adds 25 lines of tests in ApplicationTempTests.java.
The patch adds three defenses.
1. Symlink-safe existence checks via LinkOption.NOFOLLOW_LINKS
The old check, Files.exists(path), transparently follows symbolic links. The fix replaces it with:
if (!Files.exists(path, LinkOption.NOFOLLOW_LINKS)) { Files.createDirectory(path, asFileAttributes(fileSystem, DIRECTORY_PERMISSIONS)); }
With NOFOLLOW_LINKS, the check sees a symlink as a symlink instead of following it to its target. Every later attribute read also passes LinkOption.NOFOLLOW_LINKS to prevent TOCTOU (time-of-check-to-time-of-use) races.
2. Directory ownership verification
The constructor now captures the running process's identity by creating a temporary file and reading its owner:
private static @Nullable UserPrincipal directoryOwner() { try { Path tempFile = Files.createTempFile("application-temp", "-owner"); UserPrincipal owner = Files.getOwner(tempFile); Files.delete(tempFile); return owner; } catch (UnsupportedOperationException ex) { return null; } catch (IOException ex) { throw new UncheckedIOException(ex); } }
The UserPrincipal is stored in a new directoryOwner field. When the directory already exists, a new method, assertDirectoryOwnership(), compares its actual owner with the expected one and fails with an IllegalStateException if they differ. A directory that a local attacker created under their own UID is no longer accepted by the application.
3. Permission and type validation on POSIX systems
When the directory already exists on a POSIX-capable filesystem, the patch reads its PosixFileAttributes (without following links) and enforces three conditions:
- The entry is a directory, not a symlink, file, or other entity:
Assert.state(attributes.isDirectory(), ...) - Its permissions match the expected owner-only permission set:
Assert.state(DIRECTORY_PERMISSIONS.equals(attributes.permissions()), ...) - Its owner matches the running application's user:
assertDirectoryOwnership(attributes.owner(), path)
On non-POSIX filesystems, the patch still checks ownership where the OS supports Files.getOwner(), and degrades gracefully where it does not.
The new tests confirm that an IllegalStateException is raised in two cases: when a symlink is planted at the expected directory location, and when the existing directory has incorrect permissions.
Fixed Versions
| Affected Branch | Fixed Version | Availability |
|---|---|---|
| Spring Boot 4.0.x (4.0.0 through 4.0.5) | 4.0.6 | OSS (Maven Central) |
| Spring Boot 3.5.x (3.5.0 through 3.5.13) | 3.5.14 | OSS (Maven Central) |
| Spring Boot 3.4.x (3.4.0 through 3.4.15) | 3.4.16 | Enterprise Support Only |
| Spring Boot 3.3.x (3.3.0 through 3.3.18) | 3.3.19 | Enterprise Support Only |
| Spring Boot 2.7.x (2.7.0 through 2.7.32) | 2.7.33 | Enterprise Support Only |
Organizations on 3.4.x, 3.3.x, or 2.7.x without an enterprise support subscription from VMware Tanzu must migrate to the 3.5.x or 4.0.x open source branches to get the fix. The vendor states that no mitigation steps are needed beyond upgrading to the appropriate version.
Affected Systems and Versions
The vulnerability affects these Spring Boot versions:
- Spring Boot 4.0.x: versions 4.0.0 through 4.0.5
- Spring Boot 3.5.x: versions 3.5.0 through 3.5.13
- Spring Boot 3.4.x: versions 3.4.0 through 3.4.15
- Spring Boot 3.3.x: versions 3.3.0 through 3.3.18
- Spring Boot 2.7.x: versions 2.7.0 through 2.7.32
The vendor advisory notes that versions which are no longer supported are also affected.
The vulnerability is exploitable when:
- The attacker has local access to the same host as the Spring Boot application.
- The application uses the
ApplicationTempclass for temporary directory management (the default behavior). - For the most severe impact (session hijacking and code execution), the Spring Environment property
server.servlet.session.persistentis set totrue.
The risk is higher in multi-tenant environments, shared hosting platforms, and containerized deployments where multiple users or processes share a filesystem namespace.
Vendor Security History
The Spring project has an established security advisory process and a record of coordinated disclosures and fast patch availability. One notable earlier example is CVE-2022-22965, widely known as Spring4Shell, which involved remote code execution via data binding on JDK 9 and higher. Spring's handling of CVE-2026-40973 follows the same structured approach, with clear mitigation guidance and specific version matrices for both open source and commercial users.
The Italy CSIRT has also warned about recent Spring security flaws. Its warning lists CVE-2026-40973 alongside other vulnerabilities and rates the system impact as High.
References
- CVE-2026-40973: Predictable temp directory, Spring Security Advisory
- CVE-2026-40973 Detail, NVD
- Spring Boot 4.0.6 Release
- Spring Boot 3.5.14 Release
- Spring Boot 4.0.6 Available Now, Spring Blog
- GitHub Issue #50170 (3.5.x branch)
- GitHub Issue #50178 (4.0.x branch)
- Patch Commit 8e013b6 (4.0.x)
- Patch Commit 5ceb1a2 (3.5.x)
- ApplicationTemp API Documentation (Spring Boot 4.0.5)
- CVE-2022-22965: Spring Framework RCE via Data Binding on JDK 9+
- CISA Known Exploited Vulnerabilities Catalog Update, April 14 2026
- Italy CSIRT Warns of Spring Security Flaws



