ANT-2026-7WJV60DR · supabase/auth

other medium

Severity Claude medium · Security research firm - · Maintainer -

Discovered by Claude Mythos Preview

REPORT

Anthropic's analysis of this finding, sealed at approval.

ANT-2026-7WJV60DR: Manual identity linking enables account takeover via unverified email

When GOTRUE_SECURITY_MANUAL_LINKING_ENABLED is true, GET /user/identities/authorize calls linkIdentityToUser, which invokes createNewIdentity with whatever email the external provider returned without calling IsDuplicatedEmail or checking that the provider asserted the email as verified. Providers like Discord return a user's primary email even when unverified, so an attacker can link a Discord identity carrying victim@example.com to their own Supabase user. Later, when the real victim signs in via a default-linking-domain provider (e.g. Google), DetermineAccountLinking matches identities by email without filtering on verification and attaches the victim's new identity to the attacker's user. The attacker then controls the account the victim logs into.

Target

Project: supabase/auth
Location: internal/api/identity.go:135
Discovery: static analysis — not yet dynamically reproduced

Technical Details

linkIdentityToUser trusts the provider-returned email unconditionally: it neither checks IsDuplicatedEmail against existing users nor requires the provider to assert the email as verified. DetermineAccountLinking (linking.go:114) then queries identities by email alone, so an attacker-planted unverified-email identity is treated as a valid link target.

Reproduction

  1. Attacker creates a normal account on the target app.
  2. Attacker creates a Discord account and sets its email to victim@example.com without verifying it.
  3. While logged in, attacker calls GET /user/identities/authorize?provider=discord and completes OAuth; linkIdentityToUser writes an identity {provider:discord, email:victim@example.com, user_id:attacker}.
  4. Victim later signs in with Google using verified victim@example.com.
  5. DetermineAccountLinking matches the attacker's Discord identity by email and returns LinkAccount with User=attacker.
  6. Victim's Google identity is attached to the attacker's user; attacker can now log in as the victim.

[No reproducer or sanitizer output attached — request from security-cvd@anthropic.com if needed.]

Suggested Fix

Reject manual identity links whose email collides with another user, and restrict automatic account linking to identities whose email was asserted as verified by the upstream provider.

Acknowledgement

This vulnerability was discovered by Claude, Anthropic's AI assistant, and triaged by the Anthropic security team in collaboration with Anthropic Research. Please direct questions to security-cvd@anthropic.com and reference ANT-2026-7WJV60DR.


Reference: ANT-2026-7WJV60DR
Anthropic CVD Policy: https://www.anthropic.com/coordinated-vulnerability-disclosure

TIMELINE

Dates from discovery through public reveal.

  1. 2026-05-14 Reported to tracker
  2. 2026-05-14 Maintainer acknowledged
  3. 2026-05-15 Sent to maintainer
  4. 2026-08-05 Patch released
  5. 2026-08-18 Publicly revealed
PROVENANCE

SHA-3-512 hash:

c81a4fd0cd3fc7a9defc4f385a2675b0caa4db28ee228297557b9e09805c5cd4b746d33c15d7dba56a19f6b0af7da18f34f78636e5842b01f8135b380f0dccec

Committed 2026-05-17 18:02 PT

Revealed 2026-08-18 07:12 PT

Verify (download preimage.json)

Show preimage JSON
{
  "ant_id": "ANT-2026-7WJV60DR",
  "bug_class": "other",
  "claude_severity": "medium",
  "commit_sha": null,
  "created_at": "2026-05-14T22:00:14+00:00",
  "description": "When GOTRUE_SECURITY_MANUAL_LINKING_ENABLED is true, GET /user/identities/authorize calls linkIdentityToUser, which invokes createNewIdentity with whatever email the external provider returned without calling IsDuplicatedEmail or checking that the provider asserted the email as verified. Providers like Discord return a user's primary email even when unverified, so an attacker can link a Discord identity carrying victim@example.com to their own Supabase user. Later, when the real victim signs in via a default-linking-domain provider (e.g. Google), DetermineAccountLinking matches identities by email without filtering on verification and attaches the victim's new identity to the attacker's user. The attacker then controls the account the victim logs into.",
  "discovered_at": "2026-05-10T00:00:00+00:00",
  "location": "internal/api/identity.go:135",
  "poc_sha256": null,
  "preimage_version": 1,
  "project": "supabase/auth",
  "reproduction": [
    "1. Attacker creates a normal account on the target app.",
    "2. Attacker creates a Discord account and sets its email to victim@example.com without verifying it.",
    "3. While logged in, attacker calls GET /user/identities/authorize?provider=discord and completes OAuth; linkIdentityToUser writes an identity {provider:discord, email:victim@example.com, user_id:attacker}.",
    "4. Victim later signs in with Google using verified victim@example.com.",
    "5. DetermineAccountLinking matches the attacker's Discord identity by email and returns LinkAccount with User=attacker.",
    "6. Victim's Google identity is attached to the attacker's user; attacker can now log in as the victim."
  ],
  "technical_details": "linkIdentityToUser trusts the provider-returned email unconditionally: it neither checks IsDuplicatedEmail against existing users nor requires the provider to assert the email as verified. DetermineAccountLinking (linking.go:114) then queries identities by email alone, so an attacker-planted unverified-email identity is treated as a valid link target.",
  "title": "Manual identity linking enables account takeover via unverified email",
  "vendor_severity": null
}