CVE-2026-50627

Authorization Bypass
Affects
Apache CXF
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.

An Authorization Bypass vulnerability (CVE-2026-50627) has been identified in the JwtAccessTokenValidator class of the Apache CXF OAuth 2.0 module (org.apache.cxf:cxf-rt-rs-security-oauth2), which allows attackers to replay a JWT access token issued for one resource server against a different resource server, because the validator does not check the token's audience, issuer, expiry, or not-before claims.

Per OWASP: Access control enforces policy such that users cannot act outside of their intended permissions. Failures typically lead to unauthorized information disclosure, modification, or destruction of all data or performing a business function outside the user's limits.

This issue affects the org.apache.cxf:cxf-rt-rs-security-oauth2 module in Apache CXF versions <3.6.12, >=4.0.0 <4.1.7, and >=4.2.0 <4.2.2.

Details

Module Info

Vulnerability Info

This Critical-severity vulnerability is found in the org.apache.cxf:cxf-rt-rs-security-oauth2 package in multiple versions of Apache CXF. JwtAccessTokenValidator lets a JAX-RS resource server accept self-contained JWT access tokens locally, without calling back to the authorization server's introspection endpoint. It extends JoseJwtConsumer, which verifies the token's signature (or decrypts it) and then calls a validateToken(JwtToken) hook that is meant to check the token's claims. In the base class that hook is empty, and JwtAccessTokenValidator does not override it:

// rt/rs/security/jose-parent/jose/.../jwt/JoseJwtConsumer.java
public JwtToken getJwtToken(String wrappedJwtToken,
                               JweDecryptionProvider theDecryptor,
                               JwsSignatureVerifier theSigVerifier) {
    // ...
        if (!jwtConsumer.verifySignatureWith(theSigVerifier)) {
            throw new JwtException("Invalid Signature");
        }
    }

    validateToken(jwt);
    return jwt;
}

protected void validateToken(JwtToken jwt) {
}
// rt/rs/security/oauth-parent/oauth2/.../filters/JwtAccessTokenValidator.java
public class JwtAccessTokenValidator extends JoseJwtConsumer implements AccessTokenValidator {

    public AccessTokenValidation validateAccessToken(MessageContext mc,
                                                     String authScheme,
                                                     String authSchemeData,
                                                     MultivaluedMap<String, String> extraProps)
        throws OAuthServiceException {
        try {
            JwtToken token = super.getJwtToken(authSchemeData);
            return convertClaimsToValidation(token.getClaims());
        } catch (Exception ex) {
            throw new OAuthServiceException(ex);
        }
    }

    private AccessTokenValidation convertClaimsToValidation(JwtClaims claims) {
        AccessTokenValidation atv = new AccessTokenValidation();
        atv.setInitialValidationSuccessful(true);
        // ...
        List<String> audiences = claims.getAudiences();
        if (audiences != null && !audiences.isEmpty()) {
            atv.setAudiences(claims.getAudiences());
        }
        if (claims.getIssuer() != null) {
            atv.setTokenIssuer(claims.getIssuer());
        }
        // ...
        return atv;
    }
}

The bearer token comes straight from the request's Authorization header. Once the signature verifies, the validator marks the token as successfully validated and copies its claims into the AccessTokenValidation result without checking them. It does not require an iss claim, does not match the aud claim against the resource server, and does not enforce the exp, nbf, and iat time bounds. Only the coarser checks in OAuthRequestFilter remain. That filter accepts a token that carries no aud claim unless a fixed audience is configured, matches aud against the request URL by prefix only, checks the issuer only when one is configured, and never expires a token that has no exp claim. Deployments often share one authorization server and signing key across several resource servers. In that setup, a validly signed access token issued for one resource server can be accepted by another, so a token holder or anyone who captures a token can replay it against services it was never issued for (token confusion).

Mitigation

Only recent versions of Apache CXF receive community support. Older lines are 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
Critical
ID
CVE-2026-50627
PROJECT Affected
Apache CXF
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
Authorization Bypass
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.