CVE-2026-50631
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
- Product: Apache CXF
- Affected packages:
org.apache.cxf:cxf-rt-rs-security-oauth2 - Affected versions: <3.6.12, >=4.0.0 <4.1.7, >=4.2.0 <4.2.2
- GitHub repository: https://github.com/apache/cxf
- Published packages: https://central.sonatype.com/artifact/org.apache.cxf/cxf-rt-rs-security-oauth2
- Package manager: Maven
- Fixed in:
- OSS Apache CXF 3.6.12, 4.1.7, 4.2.2
- NES for Apache CXF v3.5.13, v3.4.12
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)