ANT-2026-XJKJSANG · supabase/auth

other low

Severity Claude low · Security research firm - · Maintainer -

Discovered by Claude Mythos Preview

REPORT

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

ANT-2026-XJKJSANG: Azure issuer check uses always-true boolean expression

In the Azure external auth provider (azure.go:72), the guard if !IsAzureIssuer(x) || !IsAzureCIAMIssuer(x) is always true because no issuer string can be both a v2 Azure issuer and a CIAM issuer simultaneously. As a result, expectedIssuer is unconditionally cleared and the strict per-tenant issuer comparison never fires. An attacker presenting an otherwise well-formed id_token from a different Azure tenant is not rejected early by the tenant pin; the token instead proceeds to the generic multi-tenant Azure common-key verification path. Operators who configured a specific tenant issuer and rely on this check for tenant isolation get weaker filtering than intended.

Target

Project: supabase/auth
Location: internal/api/provider/azure.go:72
Discovery: static analysis — not yet dynamically reproduced

Technical Details

The boolean uses OR of two negations where AND was intended: since IsAzureIssuer(x) and IsAzureCIAMIssuer(x) are mutually exclusive, at least one negation is always true, making the whole expression a tautology. This unconditionally sets expectedIssuer = "", neutering the subsequent equality check against the configured tenant issuer.

Reproduction

  1. Operator configures Azure provider with a specific tenant issuer URL
  2. Attacker obtains a valid, well-formed id_token from a different Azure tenant
  3. Attacker submits the token to the auth endpoint
  4. Tautological guard clears expectedIssuer so the strict tenant-issuer equality check is skipped
  5. Token proceeds to downstream common-key verification instead of being rejected early

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

Suggested Fix

Change the condition so expectedIssuer is cleared only when the configured URL is neither an Azure v2 issuer nor a CIAM issuer — i.e., use logical AND of the negations (!IsAzureIssuer(x) && !IsAzureCIAMIssuer(x)) — restoring per-tenant issuer pinning.

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-XJKJSANG.


Reference: ANT-2026-XJKJSANG
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-06-02 Patch released
  5. 2026-08-18 Publicly revealed
PROVENANCE

SHA-3-512 hash:

33feceffbe4abf6811dd3cab5c315a6e1fa1d9e3e4aaf937f4a69d8aed2512c787f3341c4055fa55907cc735e0ea4eb61a9f91cb60e9647dd4c1ae7551d3654d

Committed 2026-05-17 17:59 PT

Revealed 2026-08-18 07:12 PT

Verify (download preimage.json)

Show preimage JSON
{
  "ant_id": "ANT-2026-XJKJSANG",
  "bug_class": "other",
  "claude_severity": "low",
  "commit_sha": null,
  "created_at": "2026-05-14T22:01:37+00:00",
  "description": "In the Azure external auth provider (azure.go:72), the guard `if !IsAzureIssuer(x) || !IsAzureCIAMIssuer(x)` is always true because no issuer string can be both a v2 Azure issuer and a CIAM issuer simultaneously. As a result, expectedIssuer is unconditionally cleared and the strict per-tenant issuer comparison never fires. An attacker presenting an otherwise well-formed id_token from a different Azure tenant is not rejected early by the tenant pin; the token instead proceeds to the generic multi-tenant Azure common-key verification path. Operators who configured a specific tenant issuer and rely on this check for tenant isolation get weaker filtering than intended.",
  "discovered_at": "2026-05-10T00:00:00+00:00",
  "location": "internal/api/provider/azure.go:72",
  "poc_sha256": null,
  "preimage_version": 1,
  "project": "supabase/auth",
  "reproduction": [
    "Operator configures Azure provider with a specific tenant issuer URL",
    "Attacker obtains a valid, well-formed id_token from a different Azure tenant",
    "Attacker submits the token to the auth endpoint",
    "Tautological guard clears expectedIssuer so the strict tenant-issuer equality check is skipped",
    "Token proceeds to downstream common-key verification instead of being rejected early"
  ],
  "technical_details": "The boolean uses OR of two negations where AND was intended: since IsAzureIssuer(x) and IsAzureCIAMIssuer(x) are mutually exclusive, at least one negation is always true, making the whole expression a tautology. This unconditionally sets expectedIssuer = \"\", neutering the subsequent equality check against the configured tenant issuer.",
  "title": "Azure issuer check uses always-true boolean expression",
  "vendor_severity": null
}