Sep 11, 2026·7 min read·63 visits
Unauthenticated remote attackers can takeover ZITADEL accounts by abusing a logical flaw where ZITADEL fails to verify the email ownership claim (email_verified) from federated identity providers during automatic account linking.
An improper authentication vulnerability (CWE-287) in ZITADEL's external identity provider handler before version 4.15.3 allows remote attackers to perform complete account takeover. When auto-linking by email is enabled, ZITADEL verifies that the local target account has a verified email address but fails to verify if the external provider confirmed ownership of that same email. Attackers can exploit this by registering an unverified account with a victim's email address on a permissive external provider, leading to unauthorized account binding and persistent access.
ZITADEL is an open-source cloud-native identity management platform that provides identity federation, authentication, and authorization services. The platform is designed to handle multiple external identity providers (IdPs) via standard protocols such as OpenID Connect (OIDC) and SAML.
To simplify the authentication experience, ZITADEL includes an 'auto-linking by email' feature. This feature automatically matches and links an incoming external identity to an existing local ZITADEL account when their email addresses match, avoiding the need for manual user intervention during registration.
This vulnerability, classified as CWE-287 (Improper Authentication), arises due to a flaw in how ZITADEL validates incoming identity assertions. While ZITADEL verified that the target local account possessed a verified email status, it did not verify whether the incoming external identity provider had actually validated ownership of that email address before performing the auto-link.
The resulting impact is an authentication bypass that can lead to remote, unauthenticated account takeover. If a victim has a verified email address on a ZITADEL instance, an attacker can register that same email on a permissive external identity provider and use it to log in and automatically take control of the victim's ZITADEL account.
The core of the vulnerability lies in ZITADEL's implicit trust of the federated payload's identity claims. When a user authenticates via an external identity provider, the provider returns a payload containing user attributes. In an OIDC environment, this typically includes the email and email_verified claims.
In versions prior to 4.15.3, ZITADEL's backend logic for automatic account linking only performed validation checks on the local side of the relationship. The function checkAutoLinking checked whether the local user's email was verified in the ZITADEL database using the query NewUserVerifiedEmailSearchQuery. This check was intended to ensure that arbitrary unverified accounts could not be linked, but it failed to evaluate the security state of the incoming federated identity.
This implementation ignored the OIDC specification regarding the email_verified claim. If the external provider did not enforce email verification (a 'permissive' IdP), an attacker could register an account with a victim's email without proving ownership. Upon logging in via this IdP, the incoming payload asserted the target email address but set the email_verified attribute to false (or omitted it entirely).
Because ZITADEL skipped validating the external verification attribute, it proceeded to execute the database link. The external account was bound to the local account, establishing an authenticated session for the attacker under the victim's identity without requiring the victim's password or multi-factor authentication credentials.
The logical flaw was present in both the Go backend and the TypeScript client-side login server, requiring aligned modifications across both codebases.
In the vulnerable Go backend code within internal/api/ui/login/external_provider_handler.go, the checkAutoLinking handler did not evaluate externalUser.IsEmailVerified before processing the email search query:
// VULNERABLE Go Implementation
case domain.AutoLinkingOptionEmail:
// Email will always be checked against verified email addresses.
emailQuery, err := query.NewUserVerifiedEmailSearchQuery(string(externalUser.Email))
if err != nil {
return false, nil
}The patched version introduces a strict conditional check immediately prior to building the query. This prevents execution if the external user's email status is not verified:
// PATCHED Go Implementation
case domain.AutoLinkingOptionEmail:
// When checking for email matches, we need to make sure that both (the one from the IdP and the one in Zitadel)
// are verified to prevent potential account takeovers.
if !externalUser.IsEmailVerified {
return false, nil
}
emailQuery, err := query.NewUserVerifiedEmailSearchQuery(string(externalUser.Email))
if err != nil {
return false, nil
}A similar omission was present in the TypeScript login flow in apps/login/src/lib/server/idp-intent.ts. The server-side login logic extracted the email but bypassed checking the corresponding verification state:
// VULNERABLE TypeScript Implementation
const email = addHumanUser?.email?.email;
if (options.autoLinking === AutoLinkingOption.EMAIL && email) {
foundUser = await listUsers({ serviceConfig, email, organizationId: organization }).then((response) => {
return response.result ? response.result[0] : null;
});
}The fix introduces the emailVerified constant, which parses the OIDC verification structure and enforces that both the email and the verification assertion evaluate to true before executing the user lookup:
// PATCHED TypeScript Implementation
const email = addHumanUser?.email?.email;
const emailVerified = addHumanUser?.email?.verification?.case === "isVerified" && addHumanUser?.email?.verification?.value;
if (options.autoLinking === AutoLinkingOption.EMAIL && email && emailVerified) {
foundUser = await listUsers({ serviceConfig, email, organizationId: organization }).then((response) => {
return response.result ? response.result[0] : null;
});
}Exploiting CVE-2026-56666 requires specific environmental conditions but no advanced tooling or prior authentication. An attacker must identify a target ZITADEL instance that has enabled 'Auto-linking by email' and configured a permissive external identity provider.
To execute the exploit, the attacker first registers an account on the permissive external identity provider using the victim's email address (e.g., victim@company.com). Because the IdP is permissive, it does not mandate verification of the registered email address to complete the signup or issue tokens.
The attacker then navigates to the target ZITADEL instance and selects the option to authenticate via the permissive external provider. ZITADEL redirects the user to the provider, where the attacker logs in using the newly created unverified account.
Upon successful authentication, the external provider redirects back to ZITADEL, passing an identity token that asserts the victim's email. ZITADEL's vulnerable login handler reads this email, finds the matching, verified local user, and establishes the database link. The attacker's external profile is permanently associated with the victim's local identity, bypassing standard local authentication controls.
The successful exploitation of CVE-2026-56666 results in full account takeover. The attacker gains administrative or standard user permissions equivalent to the victim's local account within ZITADEL. This provides access to any downstream applications integrated with ZITADEL using single sign-on (SSO).
Although the vulnerability allows complete authentication bypass, the CVSS v3.1 score is rated as 4.8 (Medium) due to several restrictive environmental requirements. The 'Attack Complexity' (AC:H) is high because the target system must have a specific, vulnerable configuration, and there must be a permissive external identity provider linked to the environment.
No user interaction is required from the victim to trigger the compromise, making it a passive exploitation vector from the perspective of the target. Once the external account is linked, the attacker maintains persistent access even if the victim changes their local ZITADEL password, as federated authentication bypasses the local password validation checks entirely.
From a detection standpoint, the attack can be difficult to distinguish from a standard federated login unless administrators proactively audit changes to linked external identities. This makes the vulnerability highly attractive for targeted persistence in environments that utilize multiple external directory services.
The primary remediation strategy is upgrading the ZITADEL deployment to version 4.15.3 or higher. This update introduces the mandatory verification checks in both the backend and client-side logic, preventing unverified external claims from initiating automatic links.
If upgrading is not immediately possible, administrators must implement defensive mitigations to protect the environment. The most effective immediate workaround is to disable the 'Auto-linking by email' option within the Identity Provider (IdP) settings in the ZITADEL console. Administrators should transition to linking based on username (such as the OIDC sub claim) or enforce manual linking where users must log in to their local account before associating an external identity.
Administrators should also review the configuration of all configured external identity providers. Any provider that does not strictly enforce email verification before issuing OIDC tokens should be disabled or isolated.
To detect potential past exploitation, security teams should inspect ZITADEL's event store for historic linkings. Querying for user event types associated with identity provider associations (user.external.idp.added) allows security teams to identify any accounts that were linked prior to the application of the patch. These logs should be cross-referenced with external identity provider registration records to ensure correlation and legitimacy.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
ZITADEL ZITADEL | < 4.15.3 | 4.15.3 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-287 |
| Attack Vector | Network (AV:N) |
| CVSS Score | 4.8 |
| EPSS Score | 0.00285 (Percentile: 20.90%) |
| Impact | Account Takeover / Authentication Bypass |
| Exploit Status | poc |
| KEV Status | Not Listed |
The platform performs authentication decisions based on an external entity's assertion without verifying that the external entity validated the identity claimed.
CVE-2026-115895 is a high-severity code injection vulnerability (CWE-94) in the happy-dom npm package prior to version 21.0.4. The vulnerability exists within the ECMAScriptModuleCompiler component, which transforms ECMAScript module syntax into executable Node.js functions when JavaScript evaluation is enabled. Due to an incomplete fix for CVE-2026-33943, the compiler failed to validate local named import aliases against legal JavaScript identifier rules. Attackers supplying crafted module imports—specifically utilizing destructuring default initializers alongside JSON module attributes—can inject arbitrary JavaScript expressions directly into the host Node.js runtime context.
An improper input validation and authorization bypass vulnerability exists in the LangGraph storage layer affecting langgraph, langgraph-checkpoint-postgres, and langgraph-checkpoint-sqlite. Because relational store implementations serialize namespace tuples into dot-delimited strings without validating labels on read, search, delete, and batch operations, an attacker who controls a namespace label can inject periods (.) to traverse namespace boundaries and access, modify, or delete data belonging to other namespaces.
CVE-2026-115886 (GHSA-2wqp-q3c6-ccj5) is a Server-Side Request Forgery (SSRF) and Unsafe Reflection vulnerability in MLflow versions 3.12.0rc0 prior to 3.17.0. Unauthenticated REST API endpoints accept serialized third-party scorer JSON payloads that are dynamically deserialized and reflectively instantiated without sanitizing constructor keyword arguments. When optional dependencies such as trulens and trulens-providers-litellm are installed, attackers can inject egress-steering arguments into the scorer payload, forcing the MLflow server to dispatch outbound HTTP requests to arbitrary internal destinations or cloud metadata services.
CVE-2026-113872 (GHSA-q7qp-rjg7-q26m) is a high-severity denial-of-service vulnerability affecting the multer multipart/form-data upload middleware for Node.js and Express in versions 2.0.0 through 2.4.0. When an endpoint is configured to accept multiple files using an asynchronous fileFilter callback, a crafted, truncated multipart HTTP request can trigger an unhandled error event on the underlying busboy stream parser after request teardown has already completed. Because all error listeners are stripped during teardown, Node.js treats the resulting error event as an uncaught exception and immediately terminates the server process.
CVE-2026-115897 (also tracked as GHSA-m5mm-p8h7-m29v and aliased as CVE-2026-115754) is a Cross-Site Scripting (XSS) vulnerability in the Yahoo serialize-javascript npm package prior to version 7.1.3. The flaw exists in the regular expression used by escapeFunctionBody() to neutralize HTML script closing tags within serialized JavaScript functions. Because function bodies are sanitized in isolation before structural formatting is applied, a function whose string representation terminates directly with the sequence '</script' bypasses the positive lookahead check. When combined with serialization formatting options that introduce whitespace delimiters and a subsequent property that supplies a closing bracket, an attacker can prematurely terminate an enclosing HTML <script> block and inject arbitrary HTML or JavaScript into the rendered document.
CVE-2026-109841 is a Subresource Integrity (SRI) verification bypass vulnerability in undici, the official HTTP/1.1 and HTTP/2 client library for Node.js that powers the global fetch() implementation. The flaw stems from improper handling of case sensitivity (CWE-178) when validating cryptographic hash algorithm tokens within SRI metadata. Because undici compared incoming algorithm identifiers against a strictly lowercase set without prior ASCII-lowercase normalization, valid uppercase or mixed-case tokens such as SHA256- or Sha384- were treated as unrecognized algorithms and discarded. Under SRI forward-compatibility rules, discarding all provided tokens results in an empty integrity list, causing undici to fail open and accept tampered HTTP response bodies without cryptographic verification.