In late 2022, a security flaw was discovered in Spring Security's OAuth2 support that exposes web applications to privilege escalation attacks. Known as CVE-2022-31690, this vulnerability allows attackers to force applications to grant users more permissions than they should have by tampering with OAuth2 requests and responses ​(source)​. If your project uses Spring Security 5.7 (before 5.7.5), 5.6 (before 5.6.9), or any older, unsupported versions, read on—this affects you.

What is CVE-2022-31690?

CVE-2022-31690 is a privilege escalation vulnerability in Spring Security when acting as an OAuth2 client. Under specific conditions, a malicious user can manipulate authorization requests to obtain tokens with unintended permissions (scopes). This is possible when an OAuth2 authorization server returns an access token with an empty scope in the response. According to RFC 6749, Section 5.1, an empty scope means the token gets the *default* permissions registered for the client—not necessarily what the user or app requested.

Impact: Attackers can gain unauthorized access to protected resources by escalating their privileges, depending on the default scopes configured on the server side.

All older, unsupported versions

Key Condition:
The vulnerability only triggers if the OAuth2 Authorization Server (IdP) returns an empty scope parameter in its Access Token Response.

User initiates OAuth2 login:

User tries to sign in to your app using OAuth2 (e.g., via Google, Facebook, or your own auth server).

Authorization Server sends back an access token with an empty scope:

Instead of specifying the scopes in the response (like read or profile), the server leaves scope empty.

Spring Security client assigns default scope:

Per the OAuth2 spec (RFC 6749, Section 5.1), an empty scope means using the client’s pre-registered default scopes—which might be broader than the user should have.

How the Exploit Works (With Code Example)

Let's look at a simplified working scenario. Suppose you have a Spring Security-based app with an OAuth2 login:

# application.yml
spring:
  security:
    oauth2:
      client:
        registration:
          my-oauth:
            client-id: my-client
            client-secret: secret
            scope:
              - read
              - write

Suppose your Authorization Server (badly configured) replies like this

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 360,
  "scope": ""
}

Normally, you expect the scope to be "read" for a basic user. But the empty "scope": "" field means Spring Security will use the _default_ scopes configured for the client—which in this case might include both read and write.

Suppose you are using curl to simulate the OAuth2 token endpoint request

curl -X POST -d "grant_type=authorization_code&code=CODE&redirect_uri=http://localhost:808/login/oauth2/code/my-oauth&client_id=my-client&client_secret=secret"; \
  https://auth.example.com/oauth/token

The server gives you back

{
  "access_token": "abc.def.ghi",
  "token_type": "Bearer",
  "scope": ""  // <--- Problem here!
}

Spring Security maps this empty scope to the default, and if write is included there, the attacker can now perform write operations even if their original approval was only for read.

Official References and Resources

- Spring Security Advisory: CVE-2022-31690
- NIST NVD Entry for CVE-2022-31690
- Spring Security GitHub Fix Commit
- OAuth2 RFC 6749, Section 5.1

How to Protect Your Applications

Upgrade Immediately:

Spring Security 5.7.5 or later (if on 5.7.x)

Check Your Authorization Server:
Ensure your OAuth2 Authorization Server always returns an explicit scope in the token response, even if it matches defaults.

Monitor & Audit:
Look out for tokens with empty scopes in your logs. If you see suspicious API calls with these tokens, investigate.

Pin Down Scopes:
Don’t register broad or overly permissive default scopes.

Sample Secure Configuration

spring:
  security:
    oauth2:
      client:
        registration:
          my-oauth:
            # ... 
            scope:  # Only specify minimal required scopes!
              - read

And on your API controllers

@PreAuthorize("hasAuthority('SCOPE_read')")
public String readData() {
    // read-only logic
}

Conclusion

CVE-2022-31690 is a perfect example of how small implementation flaws—in this case, missing scopes from an OAuth2 token response—can punch huge holes into application security. Always keep your dependencies up to date and make sure your OAuth2 Authorization Server is configured according to the spec. If you’re using Spring Security 5.7.x or 5.6.x, upgrade now or risk a privilege escalation attack!

Official Patch:
Spring Security Release Notes


*Stay safe. Audit your applications regularly and follow best practices!*


> Written exclusively for your technical security insight.
>
> For questions, join the Spring Security Discussions.

Timeline

Published on: 10/31/2022 20:15:00 UTC
Last modified on: 08/08/2023 14:22:00 UTC