Safeguard
Security

CVE-2024-22234: The Spring Security Access Control Bypass Explained

CVE-2024-22234 is a broken access control flaw in Spring Security where isFullyAuthenticated returns true for a null authentication. Here is how it works and how to fix it.

Marcus Chen
DevSecOps Engineer
5 min read

CVE-2024-22234 is a broken access control vulnerability in Spring Security where a direct call to AuthenticationTrustResolver.isFullyAuthenticated(Authentication) with a null argument incorrectly returns true, potentially granting an unauthenticated request the same treatment as a fully authenticated one. It carries a CVSS v3.1 base score of 7.4 (High) and affects specific 6.1.x and 6.2.x releases. If your application calls that method directly to make authorization decisions, you need to read this.

What CVE-2024-22234 is

The vulnerability lives in the spring-security-web module. Spring Security exposes an AuthenticationTrustResolver interface whose isFullyAuthenticated(Authentication) method is meant to answer a simple question: is this a fully authenticated principal, as opposed to anonymous or remember-me? In the affected versions, when the Authentication object passed in is null, the method returns true instead of false.

That inversion is the whole bug. A null authentication should represent the absence of a verified identity, which is the opposite of "fully authenticated." Any authorization logic that trusts the return value to gate access would let a request with no authentication through.

Affected versions

The flaw affects:

  • Spring Security 6.1.0 through 6.1.6
  • Spring Security 6.2.0 through 6.2.1

It was fixed in 6.1.7 and 6.2.2. Earlier major branches such as 5.x were not called out as affected by this specific CVE, though anyone still on those branches has other reasons to upgrade. Always confirm against the official Spring advisory for your exact version.

The root cause in plain terms

Consider how a naive custom authorization check might use the resolver:

// Vulnerable pattern: trusting isFullyAuthenticated directly
public boolean canAccessAdmin(Authentication authentication) {
    AuthenticationTrustResolver resolver = new AuthenticationTrustResolverImpl();
    // In affected versions, a null authentication returns true here
    return resolver.isFullyAuthenticated(authentication);
}

If authentication is null, which can happen when the security context has not been populated for a given request path, the vulnerable versions return true. The method should treat null as "not authenticated." Because it does not, the check waves the request through.

The important nuance is that this only bites applications that call isFullyAuthenticated directly and can reach it with a null value. Standard Spring Security authorization rules built with the DSL, such as .authenticated() or .hasRole(...), do not rely on this method in a way that exposes the bug. So the practical risk is concentrated in custom code that reaches into the trust resolver itself.

Are you exploitable?

Ask three questions:

  1. Are you running Spring Security 6.1.0 to 6.1.6 or 6.2.0 to 6.2.1? Check your resolved dependency tree, not just your declared version, because Spring Boot's BOM or a transitive pin may set the effective version.
  2. Does your code call AuthenticationTrustResolver.isFullyAuthenticated(...) directly?
  3. Can that call receive a null Authentication on any reachable path?

If the answer to all three is yes, you are exploitable and should patch immediately. If you only answered yes to the first, you should still upgrade as a matter of hygiene, but the direct exposure is low.

To find the effective version, run:

# Maven
mvn dependency:tree -Dincludes=org.springframework.security

# Gradle
./gradlew dependencyInsight --dependency spring-security-web

How to fix CVE-2024-22234

The remediation is a version bump, and it is a small one.

For the 6.1.x line:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>6.1.7</version>
</dependency>

For the 6.2.x line, move to 6.2.2 or later. If you manage versions through Spring Boot, upgrade to a Boot patch release whose dependency management pulls in the fixed Spring Security version rather than pinning the module by hand, which keeps the rest of the Spring ecosystem coherent.

After upgrading, verify with the dependency tree command above that the fixed version is actually resolved, since a stray transitive constraint can silently override your intended version.

Defense in depth for authorization bugs

Patching this CVE is necessary, but the class of bug it represents, authorization logic trusting a value it should not, deserves broader defenses.

Prefer the framework's declarative authorization over hand-rolled checks. When you must interrogate authentication state in code, treat null defensively and fail closed:

public boolean canAccessAdmin(Authentication authentication) {
    if (authentication == null || !authentication.isAuthenticated()) {
        return false; // fail closed on missing identity
    }
    // ... explicit role checks
}

Add integration tests that hit protected endpoints with no credentials and assert a 401 or 403, so an access-control regression fails the build rather than reaching production. And because Spring Security is almost always a transitive dependency somewhere in a large Java estate, keep an inventory of where it resolves. An SCA tool such as Safeguard can flag a vulnerable spring-security-web version transitively, even when nothing in your own POM names it directly. For a related deep dive on Java dependency risk, see our Jackson databind security guide.

FAQ

What is the CVSS score of CVE-2024-22234?

It has a CVSS v3.1 base score of 7.4, rated High.

Which Spring Security versions are affected?

Versions 6.1.0 through 6.1.6 and 6.2.0 through 6.2.1. It is fixed in 6.1.7 and 6.2.2.

Am I vulnerable if I only use standard Spring Security authorization rules?

The exposure is concentrated in code that calls AuthenticationTrustResolver.isFullyAuthenticated(...) directly with a value that can be null. Standard declarative rules are not the direct exploitation path, but you should still upgrade.

How do I confirm my effective version?

Run mvn dependency:tree -Dincludes=org.springframework.security for Maven or ./gradlew dependencyInsight --dependency spring-security-web for Gradle to see the resolved version, which can differ from what you declared.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.