CVE-2026-50631

Concurrent Execution using Shared Resource with Improper Synchronization
Affects
Apache CXF (org.apache.cxf:cxf-rt-rs-security-oauth2)
in
Apache CXF
No items found.
Versions
<3.6.12, >=4.0.0 <4.1.7, >=4.2.0 <4.2.2

Patch Available.

Exclamation circle icon
Patch Available

This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.

Overview

Apache CXF is an open-source services framework, maintained by the Apache Software Foundation, for building and consuming web services in Java. It implements the JAX-WS and JAX-RS APIs and supports SOAP, the WS-* standards, RESTful HTTP, and OAuth 2.0 over transports such as HTTP and JMS. Its modules are published as Maven artifacts under org.apache.cxf.

A Concurrent Execution using Shared Resource with Improper Synchronization vulnerability (CVE-2026-50631) has been identified in the OAuth2 data provider (AbstractOAuthDataProvider) of Apache CXF, which allows attackers who hold a leaked refresh token to replay it in concurrent refresh requests and obtain multiple valid access tokens when refresh token recycling is disabled (recycleRefreshTokens set to false).

Per CWE: The product contains a concurrent code sequence that requires temporary, exclusive access to a shared resource, but a timing window exists in which the shared resource can be modified by another code sequence operating concurrently.

This issue affects all versions of the cxf-rt-rs-security-oauth2 module before 3.6.12, versions 4.0.0 through 4.1.6, and versions 4.2.0 through 4.2.1 of Apache CXF.

Details

Module Info

Vulnerability Info

This High-severity vulnerability is found in the cxf-rt-rs-security-oauth2 package in all versions before 3.6.12, versions 4.0.0 through 4.1.6, and versions 4.2.0 through 4.2.1 of Apache CXF.

When an OAuth2 authorization server is built on AbstractOAuthDataProvider (or one of its subclasses such as the JPA and JCache data providers) with setRecycleRefreshTokens(false), the refresh token grant is handled by refreshAccessToken. In this mode the provider keeps the existing refresh token instead of revoking it and issuing a new one. The method reads the refresh token with getRefreshToken, checks it, mints a new access token, saves it, and then links that access token back to the refresh token. None of this runs under a lock. The provider's refreshTokenLock only guards the final updateExistingRefreshToken step, not the read and check.

@Override
public ServerAccessToken refreshAccessToken(Client client, String refreshTokenKey,
                                            List<String> restrictedScopes) throws OAuthServiceException {
    RefreshToken currentRefreshToken = recycleRefreshTokens
        ? revokeRefreshToken(client, refreshTokenKey) : getRefreshToken(refreshTokenKey);
    if (currentRefreshToken == null) {
        throw new OAuthServiceException(OAuthConstants.ACCESS_DENIED);
    }
    if (OAuthUtils.isExpired(currentRefreshToken.getIssuedAt(), currentRefreshToken.getExpiresIn())) {
        if (!recycleRefreshTokens) {
            revokeRefreshToken(client, refreshTokenKey);
        }
        throw new OAuthServiceException(OAuthConstants.ACCESS_DENIED);
    }
    if (recycleRefreshTokens) {
        revokeAccessTokens(client, currentRefreshToken);
    }

    ServerAccessToken at = doRefreshAccessToken(client, currentRefreshToken, restrictedScopes);
    saveAccessToken(at);
    if (recycleRefreshTokens) {
        createNewRefreshToken(at);
    } else {
        updateExistingRefreshToken(currentRefreshToken, at);
    }
    return at;
}

This is a time-of-check time-of-use (TOCTOU) race condition. Several token endpoint requests that present the same refresh token at the same moment can all pass the lookup and expiry checks before any of them updates the stored token state. Each request then gets its own new access token. An attacker who has obtained a refresh token, or several parties replaying one leaked token, can therefore issue multiple valid access tokens in parallel. This defeats the single-use handling that the provider applies to refresh token processing. The attack is sent over the network, needs no prior authentication beyond the leaked token, and depends on winning the race window, which is why the attack complexity is rated high. The CISA-ADP score is CVSS 3.1 7.4 (AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N), which falls in the High band. Apache's own advisory (https://lists.apache.org/thread/s83t3x4r626o9h8rt0ryr1w7w53l1vv8) rates the issue low; the severity of this entry follows the CVSS score.

This vulnerability was introduced in 2016 with Apache CXF 3.1.5.

Mitigation

Only recent versions of Apache CXF are community-supported. The affected 3.5.x line is End-of-Life and will not receive public updates to address this issue.

Users of the affected components should apply one of the following mitigations:

  • Upgrade to a currently supported Apache CXF release line (3.6.x or later) that contains the fix.
  • Leverage a commercial support partner like HeroDevs for post-EOL security support.

Credits

  • Guanping Zhang (finder)
Vulnerability Details
Severity
Level
CVSS Assessment
Low
>=0 <4
Medium
>=4 <6
High
>=6 <8
Critical
>=8 <10
High
ID
CVE-2026-50631
PROJECT Affected
Apache CXF (org.apache.cxf:cxf-rt-rs-security-oauth2)
Versions Affected
<3.6.12, >=4.0.0 <4.1.7, >=4.2.0 <4.2.2
NES Versions Affected
Published date
October 1, 2026
≈ Fix date
September 29, 2026
Category
Concurrent Execution using Shared Resource with Improper Synchronization
Vex Document
Download VEXHow do I use it?
Sign up for the latest vulnerability alerts fixed in
NES for Apache CXF
Rss feed icon
Subscribe via RSS
or

By submitting the form I acknowledge receipt of our Privacy Policy.

Thanks for signing up for our Newsletter! We look forward to connecting with you.
Oops! Something went wrong while submitting the form.