CVE-2026-65583

Weak Authentication
Affects
Apache CXF
in
Apache CXF
No items found.
Versions
<3.6.12, >=4.0.0 <4.1.8, >=4.2.0 <4.2.3

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 Weak Authentication vulnerability (CVE-2026-65583) has been identified in the OpenID Connect relying-party ID token validation of Apache CXF, which allows attackers to have self-issued ID tokens accepted without the subject, audience, expiry, issued-at, and not-before checks, bypassing authentication controls when self-issued provider support is enabled.

Per OWASP: Confirmation of the user's identity, authentication, and session management is critical to protect against authentication-related attacks.

This issue affects versions prior to 3.6.12, 4.0.0 through 4.1.7, and 4.2.0 through 4.2.2 of Apache CXF.

Details

Module Info

Vulnerability Info

This Critical-severity vulnerability is found in the org.apache.cxf:cxf-rt-rs-security-sso-oidc package in versions prior to 3.6.12, 4.0.0 through 4.1.7, and 4.2.0 through 4.2.2 of Apache CXF.

OidcClaimsValidator validates the claims of ID tokens received by a CXF OpenID Connect relying party. When supportSelfIssuedProvider is enabled and no issuerId is configured, any token whose iss claim is https://self-issued.me is routed to validateSelfIssuedProvider(). That method has an empty body, and the subject, authorized party, audience, expiry, issued-at, and not-before checks all live in the else branch, so none of them run for a self-issued token:

public void validateJwtClaims(JwtClaims claims, String clientId, boolean validateClaimsAlways) {
    // validate the issuer
    String issuer = claims.getIssuer();
    if (issuer == null && validateClaimsAlways) {
        throw new OAuthServiceException("Invalid issuer");
    }
    if (supportSelfIssuedProvider && issuerId == null
        && issuer != null && SELF_ISSUED_ISSUER.equals(issuer)) {
        validateSelfIssuedProvider(claims, clientId, validateClaimsAlways);
    } else {
        if (issuer != null && !issuer.equals(issuerId)) {
            throw new OAuthServiceException("Invalid issuer");
        }
        // validate subject
        if (claims.getSubject() == null) {
            throw new OAuthServiceException("Invalid subject");
        }
        // ... authorized party, audience, expiry, issuedAt and nbf checks ...
    }
}

private void validateSelfIssuedProvider(JwtClaims claims, String clientId, boolean validateClaimsAlways) {
}

The only binding a self-issued token is meant to carry, the requirement that the sub_jwk public key's JWK thumbprint equals sub, is attempted only while choosing a signature verifier. That code looks up the issuer under a non-standard claim named issuer instead of the registered iss claim, and it does not consult issuerId. As a result, any token that carries issuer set to https://self-issued.me is verified with the public key embedded in its own sub_jwk claim, whatever its iss says:

@Override
protected JwsSignatureVerifier getInitializedSignatureVerifier(JwtToken jwt) {
    JsonWebKey key = null;
    if (supportSelfIssuedProvider && SELF_ISSUED_ISSUER.equals(jwt.getClaim("issuer"))) {
        String publicKeyJson = (String)jwt.getClaim("sub_jwk");
        if (publicKeyJson != null) {
            JsonWebKey publicKey = JwkUtils.readJwkKey(publicKeyJson);
            String thumbprint = JwkUtils.getThumbprint(publicKey);
            if (thumbprint.equals(jwt.getClaim("sub"))) {
                key = publicKey;
            }
        }
        // ...
    }
    // ...
}

As a result, a relying party that enables self-issued provider support runs no claim checks on a token whose iss is https://self-issued.me. Expired tokens, tokens that are not yet valid, tokens issued for a different client, and tokens without a subject all pass claims validation, so replayed or misdirected self-issued tokens can be used to authenticate. Separately, because the verifier trusts the non-standard issuer claim, an attacker can sign a token with their own key, embed that key in sub_jwk, and set iss to the configured provider; the token is then verified with the attacker's key and accepted as one issued by that provider. Self-issued provider support is disabled by default, so only deployments that call setSupportSelfIssuedProvider(true) are exposed, whether or not an issuer id is configured.

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-65583
PROJECT Affected
Apache CXF
Versions Affected
<3.6.12, >=4.0.0 <4.1.8, >=4.2.0 <4.2.3
NES Versions Affected
Published date
September 26, 2026
≈ Fix date
September 29, 2026
Category
Weak Authentication
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.