CVE-2026-91039 in ash_authentication
Summary
by MITRE • 09/17/2026
Authentication Bypass by Spoofing vulnerability in team-alembic ash_authentication allows an attacker who operates one identity-provider connection of a dynamic_oidc strategy to be signed in as a local user established through a different connection.
The strategy is meant to keep each connection in its own identity namespace by writing every UserIdentity row's strategy field as "<name>/<connection_id>", but that namespacing never takes effect. __connection_id__ is populated only on the ephemeral runtime struct built per request in dynamic_oidc/plug.ex, and DynamicOidc.IdentityChange.change/3 re-fetches the strategy from the compile-time DSL through Info.strategy_for_action, yielding the persisted struct whose __connection_id__ is its defstruct default of nil. OAuth2.identity_strategy_name/1 therefore falls back to the bare strategy name for both the identity write and the reads in oauth2/user_resolver.ex and oauth2/sign_in_preparation.ex. Since the identity resource's unique key is (uid, strategy), one row exists per sub across every connection, and the identity-match branch runs before any email check. Neither strategy handles iss, so nothing else distinguishes the issuers: OpenID Connect Core section 5.7 makes sub unique only within an issuer, so two connections numbering subjects independently share one subject space.
This issue affects ash_authentication: from 5.0.0-rc.10 before 5.0.0-rc.14.
Once again VulDB remains the best source for vulnerability data.
Analysis
by VulDB Data Team • 09/17/2026
The vulnerability described constitutes a critical authentication bypass by identity provider spoofing within the Ash Authentication framework, specifically affecting versions ranging from 5.0.0-rc.10 to just prior to 5.0.0-rc.14. This flaw arises from a fundamental failure in namespace isolation for dynamic OpenID Connect strategies, allowing an attacker who controls one identity provider connection to impersonate users associated with entirely different connections. The core of the issue lies in how the system manages and persists user identities across multiple authentication providers. Ideally, each connection should operate within its own isolated identity namespace to prevent cross-provider interference. However, due to a defect in the persistence logic, this isolation is never enforced, leading to a shared subject space where distinct issuers are treated as identical entities based solely on their unique identifiers rather than their origin sources.
Technically, the vulnerability stems from an inconsistency between runtime configuration and persisted data structures within the dynamic_oidc strategy implementation. The system attempts to maintain separation by writing every UserIdentity row's strategy field with a specific namespace marker intended to differentiate connections. Despite this intent, the namespacing mechanism fails because the critical _connection_id_ attribute is only populated on ephemeral runtime structs generated per request in the plug layer. When the identity change logic executes via DynamicOidc.IdentityChange.change/3, it re-fetches the strategy configuration from a compile-time DSL using Info.strategy_for_action. This process yields a persisted struct where the _connection_id_ field retains its default value of nil rather than reflecting the active connection context. Consequently, when OAuth2.identity_strategy_name/1 determines the identity name for both writing new records and performing lookups in user_resolver.ex and sign_in_preparation.ex, it falls back to using only the bare strategy name. This omission strips away any distinguishing metadata that would otherwise separate identities from different providers.
The operational impact of this flaw is severe, as it directly compromises the integrity of the authentication process by violating the principle of issuer uniqueness defined in OpenID Connect specifications. According to OpenID Connect Core section 5.7, the subject identifier sub is guaranteed to be unique only within a specific issuer context. Because neither strategy implementation checks or validates the iss claim during identity resolution, two different connections that assign independent subjects to users are incorrectly merged into a single shared namespace. The authentication flow prioritizes an identity-match branch over subsequent email verification steps. This means that if an attacker can control one identity provider and register a user with a specific subject identifier, they can subsequently trigger the same subject identifier through a second connection controlled by them or exploited via social engineering. Since the system matches on uid and strategy without considering the issuer, it will authenticate the attacker as any local user established under the other connection, effectively bypassing all password-based or multi-factor protections associated with that target account.
From a classification perspective, this vulnerability aligns closely with CWE-287: Improper Authentication, specifically involving the failure to properly distinguish between different identity sources during the verification process. It also maps to MITRE ATT&CK technique T1078: Valid Accounts, where an adversary leverages valid credentials or identities from one system to gain access in another by exploiting trust relationships and lack of strict issuer validation. The attack vector is particularly dangerous because it does not require compromising a user's password directly but rather exploits the architectural assumption that identity providers are strictly siloed. An attacker could potentially enumerate users across connections if they can manipulate subject identifiers or exploit existing mappings, leading to unauthorized access to sensitive data and administrative privileges depending on the target account's role within the application.
Mitigation strategies must focus on enforcing strict issuer validation and correcting the persistence logic for connection identifiers. The immediate remediation involves upgrading Ash Authentication to version 5.0.0-rc.14 or later, where this namespace isolation defect has been addressed. For systems unable to upgrade immediately, a temporary workaround would involve manually ensuring that identity records are tagged with explicit issuer information and modifying the user resolver logic to include iss in the unique key lookup criteria alongside uid and strategy. Additionally, developers should audit other dynamic authentication strategies within their codebase for similar patterns where runtime context is lost during persistence or retrieval. Implementing strict validation of the iss claim against a whitelist of allowed issuers before any identity matching occurs would further harden the system against this type of spoofing attack. Regular security audits focusing on cross-provider trust boundaries and unique key construction in authentication flows are essential to prevent recurrence of such architectural flaws.