dynamic_oidc identities are not namespaced by connection in ash_authentication, allowing cross-connection account takeover

Summary

CVECVE-2026-91039
StatePUBLISHED
AssignerEEF
Source PriorityCVE Program / NVD first with legacy fallback
Published2026-09-17 16:18:28 UTC
Updated2026-09-17 20:18:52 UTC
DescriptionAuthentication 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.

Risk And Classification

Primary CVSS: v4.0 9.1 CRITICAL from 6b3ad84c-e1a6-4bf7-a703-f496b71e49db

CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Problem Types: CWE-290 | CWE-290 CWE-290 Authentication Bypass by Spoofing


VersionSourceTypeScoreSeverityVector
4.06b3ad84c-e1a6-4bf7-a703-f496b71e49dbSecondary9.1CRITICALCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/C...
4.0CNACVSS9.1CRITICALCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N

CVSS v4.0 Breakdown

Attack Vector
Network
Attack Complexity
Low
Attack Requirements
Present
Privileges Required
None
User Interaction
None
Confidentiality
High
Integrity
High
Availability
None
Sub Conf.
None
Sub Integrity
None
Sub Availability
None

CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Vendor Declared Affected Products

SourceVendorProductVersionPlatforms
CNA Team-alembic Ash Authentication affected 5.0.0-rc.10 5.0.0-rc.14 semver Not specified
CNA Team-alembic Ash Authentication affected 64530644f9b37ebb76ca14aeb83a77597a0034b7 73ad16e452670bbf843550a13361bd41e72ad964 git Not specified

References

ReferenceSourceLinkTags
cna.erlef.org/cves/CVE-2026-91039.html 6b3ad84c-e1a6-4bf7-a703-f496b71e49db cna.erlef.org
github.com/team-alembic/ash_authentication/security/advisories/GHSA-73j9... 6b3ad84c-e1a6-4bf7-a703-f496b71e49db github.com
github.com/team-alembic/ash_authentication/commit/73ad16e452670bbf843550... 6b3ad84c-e1a6-4bf7-a703-f496b71e49db github.com
osv.dev/vulnerability/EEF-CVE-2026-91039 6b3ad84c-e1a6-4bf7-a703-f496b71e49db osv.dev
github.com/team-alembic/ash_authentication/commit/64530644f9b37ebb76ca14... 6b3ad84c-e1a6-4bf7-a703-f496b71e49db github.com
CVE Program record CVE.ORG www.cve.org canonical
NVD vulnerability detail NVD nvd.nist.gov canonical, analysis

Vendor Comments And Credit

Discovery Credit

CNA: Jace (en)

CNA: Jonatan Männchen / EEF (en)

CNA: manus-pi (en)

CNA: James Harton (en)

Additional Advisory Data

Solutions

CNA: Upgrading is not sufficient on its own, for two reasons. Namespacing changes the value the identity lookup keys on, so UserIdentity rows written before the fix, all holding the bare strategy name, no longer match. Each row's strategy must be relinked in place to "<name>/<connection_id>". Deleting the rows does not work: the block is the account match that follows, refused under the default on_untrusted_email_match :reject whether the row exists or not, and deleting also discards the stored refresh token. Where a deployment has one connection the mapping is unambiguous and the update is mechanical, but it must run in the same deployment as the upgrade and before users sign in, or a newly written namespaced row can collide with a surviving bare row on the (uid, strategy) index. The fix also cannot separate accounts already merged, and the merge is not detectable from the database, because a collision never produced two rows to compare: the second user's identity was never created and the surviving row looks legitimate. Deployments running more than one connection must audit out of band, by exporting each connection's set of sub values from its identity provider and intersecting them. Any sub present in more than one set identifies an account that may have been merged.

© CVE.report 2026

Use of this information constitutes acceptance for use in an AS IS condition. There are NO warranties, implied or otherwise, with regard to this information or its use. Any use of this information is at the user's risk. It is the responsibility of user to evaluate the accuracy, completeness or usefulness of any information, opinion, advice or other content. EACH USER WILL BE SOLELY RESPONSIBLE FOR ANY consequences of his or her direct or indirect use of this web site. ALL WARRANTIES OF ANY KIND ARE EXPRESSLY DISCLAIMED. This site will NOT BE LIABLE FOR ANY DIRECT, INDIRECT or any other kind of loss.

CVE, CWE, and OVAL are registred trademarks of The MITRE Corporation and the authoritative source of CVE content is MITRE's CVE web site. This site includes MITRE data granted under the following license.

Free CVE JSON API cve.report/api

CVE.report and Source URL Uptime Status status.cve.report