Spring Boot CVE-2026-40973: Overview of Predictable ApplicationTemp Directory Takeover Leading to Session Hijacking and Code Execution

A brief summary of CVE-2026-40973, a high severity insecure temporary file vulnerability in Spring Boot that allows local attackers to hijack the ApplicationTemp directory for session theft or arbitrary code execution. Includes patch details and affected version matrix.

CVE Analysis

8 min read

ZeroPath CVE Analysis
ZeroPath CVE Analysis

2026-04-27

Spring Boot CVE-2026-40973: Overview of Predictable ApplicationTemp Directory Takeover Leading to Session Hijacking and Code Execution
Experimental AI-Generated Content

This CVE analysis is an experimental publication that is completely AI-generated. The content may contain errors or inaccuracies and is subject to change as more information becomes available. We are continuously refining our process.

If you have feedback, questions, or notice any errors, please reach out to us.

[email protected]

Introduction

A predictable temporary directory in Spring Boot's ApplicationTemp class allows a local attacker to hijack the location used for session persistence and other sensitive temporary data, potentially leading to authenticated session theft or arbitrary code execution. For any organization running Spring Boot applications in multi-tenant environments or on shared hosts, this vulnerability quietly turns a common framework convenience into a local privilege escalation path.

Spring Boot is the most widely adopted Java framework for building web applications and microservices. Given its ubiquity across enterprise environments, the blast radius of CVE-2026-40973 is significant even though exploitation requires local access. The CVSS base score of 7.0 (HIGH) reflects the combination of high confidentiality, integrity, and availability impact with the constraint of local access and high attack complexity.

Technical Information

Root Cause: Predictable Directory Names Without Ownership Verification

The vulnerability resides in the ApplicationTemp class, which provides Spring Boot applications with a dedicated temporary directory. According to the Spring Boot API documentation, while different Spring Boot applications receive different temporary locations, restarting a specific application yields the exact same directory location. This deterministic behavior is the first ingredient of the vulnerability.

The second ingredient is the absence of any validation on an existing directory at that path. Prior to the fix, the code used Files.exists(path) to check whether the temporary directory already existed. This call transparently follows symbolic links, meaning an attacker who placed a symlink at the predictable path could redirect the application's temporary storage to an attacker-controlled location without the application noticing.

There was also no ownership verification. If the directory already existed (created by another user), the application would simply use it without checking who owned it.

Attack Flow

The exploitation of CVE-2026-40973 follows a specific sequence:

  1. Predict the directory path. The attacker, who has local access to the host, determines the predictable temporary directory path that a target Spring Boot application will use. Because ApplicationTemp generates the same path for the same application across restarts, this is straightforward.

  2. Pre-create or symlink the directory. Before the application starts (or restarts), the attacker either creates a directory at the predicted path under their own user account, or plants a symbolic link pointing to an attacker-controlled directory.

  3. Wait for application restart. The application starts and finds the directory (or symlink) already in place. The old code's Files.exists(path) call follows the symlink and sees a valid directory, so it proceeds without creating a new one.

  4. Exploit session persistence. If the application has server.servlet.session.persistent set to true, session data is written to and read from this compromised directory across restarts. The attacker now has two exploitation options:

    • Session hijacking: Read the stored session information to impersonate authenticated users.
    • Code execution via deserialization: Place a malicious gadget chain in the session data. When the application deserializes this data on restart, it executes arbitrary code under the application's user privileges.

CWE Classification

This vulnerability is classified under CWE-377: Insecure Temporary File, which describes the creation of temporary files in a manner that allows local attackers to interfere with the file's intended use.

Patch Information

The Spring Boot team released the official patch on April 23, 2026, authored and committed by Andy Wilkinson. The fix was originally 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). The change modifies a single production file, ApplicationTemp.java, with 57 additions and 4 deletions, plus 25 lines of new tests in ApplicationTempTests.java.

The patch introduces three key defense mechanisms:

Previously, the code checked for the directory with Files.exists(path), which transparently follows symbolic links. The fix replaces this with:

if (!Files.exists(path, LinkOption.NOFOLLOW_LINKS)) { Files.createDirectory(path, asFileAttributes(fileSystem, DIRECTORY_PERMISSIONS)); }

By using NOFOLLOW_LINKS, the check now detects a symlink as a symlink rather than blindly following it to the target. All subsequent attribute reads also pass 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); } }

This UserPrincipal is stored in a new directoryOwner field. When an existing directory is found, a new method assertDirectoryOwnership() compares the directory's actual owner against the expected one, failing with an IllegalStateException if they differ. This prevents a local attacker who created the directory under their own UID from having it accepted by the application.

3. Permission and type validation on POSIX systems

On POSIX-capable filesystems, when the directory already exists, the patch reads PosixFileAttributes (without following links) and enforces that:

  • The entry is truly 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, ownership is still checked where the OS supports Files.getOwner(), gracefully degrading if unsupported.

The accompanying tests validate that an IllegalStateException is raised both when a symlink is planted at the expected directory location and when the existing directory has incorrect permissions.

Fixed Versions

Affected BranchFixed VersionAvailability
Spring Boot 4.0.x (4.0.0 through 4.0.5)4.0.6OSS (Maven Central)
Spring Boot 3.5.x (3.5.0 through 3.5.13)3.5.14OSS (Maven Central)
Spring Boot 3.4.x (3.4.0 through 3.4.15)3.4.16Enterprise Support Only
Spring Boot 3.3.x (3.3.0 through 3.3.18)3.3.19Enterprise Support Only
Spring Boot 2.7.x (2.7.0 through 2.7.32)2.7.33Enterprise 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 receive the fix. The vendor states that no further mitigation steps are necessary beyond applying the appropriate version upgrade.

Affected Systems and Versions

The vulnerability affects the following 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 also notes that versions which are no longer supported are affected as well.

The vulnerability is exploitable when:

  • The attacker has local access to the same host as the Spring Boot application.
  • The application uses the ApplicationTemp class for temporary directory management (default behavior).
  • For the most severe impact (session hijacking and code execution), the Spring Environment property server.servlet.session.persistent must be set to true.

Multi-tenant environments, shared hosting platforms, and containerized deployments where multiple users or processes share a filesystem namespace are at elevated risk.

Vendor Security History

The Spring project maintains a mature security advisory process with a track record of coordinated disclosures and rapid patch availability. A notable prior example is CVE-2022-22965, widely known as Spring4Shell, which involved remote code execution via data binding on JDK 9 and higher. The handling of CVE-2026-40973 demonstrates a continuation of this structured approach, providing clear mitigation guidance and specific version matrices for both open source and commercial users.

The Italy CSIRT has also issued warnings regarding recent Spring security flaws, highlighting CVE-2026-40973 alongside other vulnerabilities and assessing the system impact rating as High.

References

Detect & fix
what others miss

Security magnifying glass visualization