Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-55672

CVE-2026-55672: ZITADEL Auth Bypass Vulnerability

CVE-2026-55672 is an authentication bypass flaw in ZITADEL identity management platform that allows intercepted tokens to be exchanged under different clients. This article covers technical details, affected versions, and patches.

Published:

CVE-2026-55672 Overview

ZITADEL, an open source identity and access management platform, contains an authentication flaw in its OAuth2 and OpenID Connect (OIDC) token exchange flows. Versions prior to 3.4.12 and 4.15.2 fail to verify that the client presenting an authorization code, refresh token, or device code matches the client that initiated the authorization request. An attacker who intercepts a grant or refresh token can redeem it under a different registered client, breaking the OAuth2 client binding assumption. The issue is tracked as [CWE-287: Improper Authentication] and is fixed in ZITADEL versions 3.4.12 and 4.15.2.

Critical Impact

Intercepted OAuth2 authorization codes, refresh tokens, or device codes can be exchanged by an attacker-controlled client, enabling unauthorized access to user resources and identity assertions.

Affected Products

  • ZITADEL versions prior to 3.4.12
  • ZITADEL versions prior to 4.15.2 (4.x branch)
  • Deployments exposing OAuth2 CodeExchange, RefreshToken, and Device Authorization Grant endpoints

Discovery Timeline

Technical Details for CVE-2026-55672

Vulnerability Analysis

ZITADEL implements the OAuth2 and OIDC token endpoints in its Go codebase under internal/api/oidc/. During the authorization code exchange, refresh token, and device code flows, the server retrieves the stored authorization request associated with the presented grant. The server then issues tokens without confirming that the client_id of the currently authenticated client matches the client_id recorded on the original authorization request.

This breaks a core OAuth2 security invariant defined in RFC 6749 Section 4.1.3, which requires the token endpoint to ensure that an authorization code is bound to the client to which it was issued. As a result, a malicious client that obtains another client's authorization code or refresh token can redeem it and receive access and identity tokens scoped to the original user.

Root Cause

The root cause is a missing equality check between authReq.GetClientID() and the authenticated client.client.ClientID in the token endpoint handlers. For device authorization, the CreateOIDCSessionFromDeviceAuth command did not receive the requesting client's identifier, so it could not validate binding at session creation.

Attack Vector

An attacker must first obtain a valid authorization code, refresh token, or device code belonging to a legitimate flow. Interception paths include referer leakage, misconfigured redirect URIs, logs, browser history on shared devices, or a compromised client. The attacker then authenticates to the ZITADEL token endpoint as a different registered client and submits the intercepted grant, receiving tokens for the victim user.

go
// Patch: internal/api/oidc/token_code.go - client_id binding check
		return nil, err
	}

+	if authReq.GetClientID() != client.client.ClientID {
+		return nil, oidc.ErrInvalidClient().WithDescription("client_id does not correspond to the client_id in the authorization request")
+	}
+
	if challenge := authReq.GetCodeChallenge(); challenge != nil || client.AuthMethod() == oidc.AuthMethodNone {
		if err = op.AuthorizeCodeChallenge(req.CodeVerifier, challenge); err != nil {
			return nil, err

Source: ZITADEL commit 5624030

go
// Patch: internal/api/oidc/token_device.go - propagate ClientID into device session
-	session, err := s.command.CreateOIDCSessionFromDeviceAuth(ctx, r.Data.DeviceCode, client.client.BackChannelLogoutURI)
+	session, err := s.command.CreateOIDCSessionFromDeviceAuth(ctx, r.Data.DeviceCode, client.client.BackChannelLogoutURI, client.client.ClientID)
	if err == nil {
		return response(s.accessTokenResponseFromSession(ctx, client, session, "", client.client.ProjectID, client.client.ProjectRoleAssertion, client.client.AccessTokenRoleAssertion, client.client.IDTokenRoleAssertion, client.client.IDTokenUserinfoAssertion))
	}
+	if errors.Is(err, oidc.ErrInvalidClient()) {
+		return nil, err
+	}

Source: ZITADEL commit 5b1708e

Detection Methods for CVE-2026-55672

Indicators of Compromise

  • Token endpoint requests where the authenticated client_id does not match the client_id recorded on the originating authorization request in ZITADEL audit logs.
  • Successful token issuance immediately followed by access from IP addresses, user agents, or ASNs that do not align with the legitimate client application.
  • Refresh token exchanges from a client that has no prior history of interactive authorization flows for the affected user.

Detection Strategies

  • Correlate /oauth/v2/token and /oauth/v2/device_token events with the original /oauth/v2/authorize request to confirm the client_id is consistent across the flow.
  • Alert on any use of an authorization code, refresh token, or device code by a client identifier that differs from the one that initiated the request.
  • Baseline expected client-to-user mappings and flag exchanges that break those relationships, particularly across tenants or projects.

Monitoring Recommendations

  • Enable verbose OIDC event logging in ZITADEL and forward it to a centralized analytics platform for retention and correlation.
  • Monitor for unusual increases in invalid_client errors after upgrading, which indicate previously accepted cross-client exchanges are now being rejected.
  • Track the population of registered OAuth clients and alert on newly created clients that immediately begin exchanging tokens for existing users.

How to Mitigate CVE-2026-55672

Immediate Actions Required

  • Upgrade ZITADEL to version 3.4.12 or 4.15.2 as published in the ZITADEL v3.4.12 release and ZITADEL v4.15.2 release.
  • Rotate any long-lived refresh tokens issued by vulnerable versions and force reauthentication for high-value users and service accounts.
  • Review OAuth client inventories and remove or disable clients that are no longer in active use to reduce the attacker's set of usable client identities.

Patch Information

The fix is delivered in ZITADEL v3.4.12 and v4.15.2. The patches, referenced in commits 5624030 and 5b1708e, add a client_id binding check in internal/api/oidc/token_code.go and propagate the authenticated client identifier into device authorization session creation in internal/api/oidc/token_device.go. Full technical context is available in GHSA-xqxv-4jc2-x56x.

Workarounds

  • Enforce PKCE (Proof Key for Code Exchange) with S256 on all public and confidential clients so that intercepted codes cannot be redeemed without the original code verifier.
  • Restrict redirect URIs to exact matches and disable wildcard patterns to reduce authorization code leakage.
  • Shorten authorization code and refresh token lifetimes and require reauthentication for sensitive scopes until the patched version is deployed.
bash
# Verify installed ZITADEL version and upgrade
kubectl -n zitadel get deploy zitadel -o jsonpath='{.spec.template.spec.containers[0].image}'

# Upgrade to a patched version (Helm example)
helm repo update
helm upgrade zitadel zitadel/zitadel \
  --namespace zitadel \
  --version <chart-version-shipping-3.4.12-or-4.15.2>

# Confirm the running version reflects the patched release
kubectl -n zitadel rollout status deploy/zitadel

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.