Skip to content

fix(sso): re-check domain conflict before write and reject IP-address domains#4825

Merged
waleedlatif1 merged 1 commit into
stagingfrom
waleedlatif1/sso-domain-conflict-fix
May 31, 2026
Merged

fix(sso): re-check domain conflict before write and reject IP-address domains#4825
waleedlatif1 merged 1 commit into
stagingfrom
waleedlatif1/sso-domain-conflict-fix

Conversation

@waleedlatif1
Copy link
Copy Markdown
Collaborator

Summary

  • Re-run the SSO domain-ownership conflict check immediately before auth.api.registerSSOProvider, in addition to the early fail-fast check, so the gap between check and write no longer spans the OIDC discovery fetches (narrows the TOCTOU window from seconds to ms).
  • normalizeSSODomain now rejects bare IPv4 addresses and numeric TLDs (e.g. 10.0.0.1), which are never registrable email domains.
  • Full atomicity (unique index on lower(domain)) is blocked on deduping existing duplicate provider rows — tracked in SSO: make domain uniqueness atomic — dedup ssoProvider rows + add lower(domain) unique index #4824.

Type of Change

  • Bug fix

Testing

Tested manually; added unit cases for IP/numeric-TLD rejection. (Existing SSO register route tests cover the conflict/ownership paths.)

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link
Copy Markdown

vercel Bot commented May 31, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped May 31, 2026 3:56am

Request Review

@cursor
Copy link
Copy Markdown

cursor Bot commented May 31, 2026

PR Summary

Medium Risk
Touches SSO registration and tenant domain ownership; the second conflict check reduces race risk but full DB uniqueness is still pending.

Overview
Narrows a time-of-check/time-of-use gap on SSO domain registration by running the same domain-ownership conflict check again immediately before registerSSOProvider, after OIDC discovery and config assembly, so a domain cannot be claimed by another tenant during the long middle phase of the request.

Conflict handling is refactored into shared findDomainConflict / domainConflictResponse helpers used for both the early and pre-write checks.

normalizeSSODomain now rejects hosts whose final label is all digits (bare IPv4-style names and numeric pseudo-TLDs such as company.123), with matching unit tests.

Reviewed by Cursor Bugbot for commit 6193c4a. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 31, 2026

Greptile Summary

This PR narrows the TOCTOU window in the SSO domain-conflict check by extracting the DB lookup into a reusable findDomainConflict closure and adding a second invocation immediately before auth.api.registerSSOProvider. It also strengthens normalizeSSODomain to reject any domain whose TLD (last label) is all-digits, blocking bare IPv4 addresses and numeric TLDs.

  • domain.ts: Adds a single-line guard after the existing label-length check; IP addresses like 10.0.0.1 are now rejected because their final octet is all-numeric.
  • route.ts: Refactors the inline conflict query and 409 response into closures and re-runs the conflict check just before the provider write, reducing the race window from the length of OIDC discovery to near-zero.
  • domain.test.ts: Adds a focused test case covering IPv4 and numeric-TLD inputs, all three of which now return null.

Confidence Score: 5/5

Safe to merge — the changes are a focused, additive hardening of the SSO registration path with no regressions introduced.

The numeric-TLD guard in domain.ts is a single-line addition that is provably correct given the earlier regex already guarantees at least one dot. The findDomainConflict refactor in route.ts is a pure extraction with identical semantics to the original inline query, and the second pre-write invocation correctly closes the gap that previously spanned the full OIDC discovery round-trip. New tests directly exercise the added rejection paths.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/lib/auth/sso/domain.ts Adds numeric-TLD guard after label-length check; correctly relies on the earlier regex ensuring at least one dot, making array access safe.
apps/sim/app/api/auth/sso/register/route.ts Refactors domain-conflict check into a reusable async closure and adds a second pre-write check to narrow the TOCTOU window; logic and closure captures are correct.
apps/sim/lib/auth/sso/domain.test.ts New test block covers IPv4 (two addresses) and numeric-TLD rejection; tests are correct and match the implementation.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Route as SSO Register Route
    participant DB as Database
    participant Auth as auth.api

    Client->>Route: POST /api/auth/sso/register
    Route->>Route: normalizeSSODomain()
    Route->>DB: findDomainConflict() check 1
    DB-->>Route: conflict 409 or continue
    Route->>Route: Build OIDC/SAML config
    Route->>DB: findDomainConflict() check 2
    DB-->>Route: conflict 409 or continue
    Route->>Auth: registerSSOProvider()
    Auth-->>Route: providerId
    Route-->>Client: 200 success
Loading

Reviews (1): Last reviewed commit: "fix(sso): re-check domain conflict befor..." | Re-trigger Greptile

@waleedlatif1 waleedlatif1 merged commit e8f6485 into staging May 31, 2026
14 checks passed
@waleedlatif1 waleedlatif1 deleted the waleedlatif1/sso-domain-conflict-fix branch May 31, 2026 04:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant