Skip to content

[codex] fix SSO domain lookup ID disclosure#2019

Open
riderx wants to merge 3 commits intomainfrom
codex/fix-sso-domain-id-leak
Open

[codex] fix SSO domain lookup ID disclosure#2019
riderx wants to merge 3 commits intomainfrom
codex/fix-sso-domain-id-leak

Conversation

@riderx
Copy link
Copy Markdown
Member

@riderx riderx commented May 2, 2026

Summary (AI generated)

  • Removed internal org_id and provider_id fields from the unauthenticated SSO domain check response.
  • Restricted SSO lookup RPC execution to service_role and moved server-side lookup calls to the admin client.
  • Updated frontend response types and added regression coverage for the public response shape.

Motivation (AI generated)

GHSA-c5jf-5wxg-mgrq reported that unauthenticated callers could enumerate domains and map them to internal organization/provider identifiers. The endpoint only needs to tell the login flow whether SSO exists and whether it is enforced.

Business Impact (AI generated)

This reduces tenant reconnaissance risk for Capgo customers without changing the login UX or plugin/API compatibility surface.

Test Plan (AI generated)

  • bun lint
  • bun lint:backend
  • bunx eslint tests/sso-check-domain-response.unit.test.ts tests/sso.test.ts tests/security-definer-execute-hardening.test.ts
  • sqlfluff lint --dialect postgres supabase/migrations/20260502134501_restrict_sso_lookup_rpc_access.sql
  • bunx vitest run tests/sso-check-domain-response.unit.test.ts
  • bun typecheck
  • Full local tests/sso.test.ts was not run because Docker/OrbStack was not running locally.

Generated with AI

Summary by CodeRabbit

Release Notes

  • Refactor

    • Modified the SSO domain check response structure, removing specific provider and organization identifiers from the returned payload. Core validation and error handling remain unaffected.
  • Tests

    • Updated test assertions to reflect the revised response structure.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 2, 2026

📝 Walkthrough

Walkthrough

The SSO domain check endpoint was updated to remove provider_id and org_id fields from the successful response JSON. Both the backend handler and the corresponding test assertion were updated to reflect this change.

Changes

SSO Domain Check Response Update

Layer / File(s) Summary
API Response
supabase/functions/_backend/private/sso/check-domain.ts
Removes provider_id and org_id from the successful SSO provider response JSON payload.
Test Assertions
tests/sso.test.ts
Updates domain normalization test to assert provider_id and org_id are undefined in the response instead of containing specific values.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

Possibly related PRs

Poem

🐰 A field or two, we gently spare,
The domain check flows light and bare,
No IDs linger in the reply,
Just flags of truth as we pass by! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title '[codex] fix SSO domain lookup ID disclosure' clearly and concisely summarizes the main change: removing ID fields from SSO domain lookup responses to prevent information disclosure.
Description check ✅ Passed The description provides a summary, detailed motivation (including CVE reference), business impact, and comprehensive test plan with specific commands executed, addressing most template sections effectively.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-sso-domain-id-leak

Review rate limit: 4/5 reviews remaining, refill in 12 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented May 2, 2026

Merging this PR will not alter performance

✅ 28 untouched benchmarks


Comparing codex/fix-sso-domain-id-leak (a26b81e) with main (21c4c38)

Open in CodSpeed

@riderx riderx marked this pull request as ready for review May 2, 2026 14:13
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
supabase/functions/_backend/private/sso/check-domain.ts (1)

103-110: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Remove internal identifiers from the public-path log payload.

provider_id and org_id are still written to logs on the anonymous lookup path, which reintroduces the tenant-reconnaissance leak this change is trying to close.

🔧 Proposed fix
       cloudlog({
         requestId,
         context: 'check_domain - SSO provider found',
         domain,
         enforce_sso: enforcementRow?.enforce_sso,
-        provider_id: legacyRow?.provider_id,
-        org_id: enforcementRow?.org_id ?? legacyRow?.org_id,
       })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@supabase/functions/_backend/private/sso/check-domain.ts` around lines 103 -
110, The cloudlog call in check-domain's anonymous lookup path is emitting
internal identifiers (provider_id and org_id), which leaks tenant info; remove
provider_id and org_id from the log payload in the cloudlog invocation (the call
that currently includes requestId, context: 'check_domain - SSO provider found',
domain, enforce_sso, provider_id, org_id) so only non-identifying fields (e.g.,
requestId, context, domain, enforce_sso) are logged; ensure any references to
legacyRow?.provider_id or enforcementRow?.org_id are not logged or included in
the cloudlog payload and instead kept only for internal logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@supabase/functions/_backend/private/sso/check-domain.ts`:
- Around line 103-110: The cloudlog call in check-domain's anonymous lookup path
is emitting internal identifiers (provider_id and org_id), which leaks tenant
info; remove provider_id and org_id from the log payload in the cloudlog
invocation (the call that currently includes requestId, context: 'check_domain -
SSO provider found', domain, enforce_sso, provider_id, org_id) so only
non-identifying fields (e.g., requestId, context, domain, enforce_sso) are
logged; ensure any references to legacyRow?.provider_id or
enforcementRow?.org_id are not logged or included in the cloudlog payload and
instead kept only for internal logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 260554ee-240d-463b-8698-ebbcaeaa446a

📥 Commits

Reviewing files that changed from the base of the PR and between 97ee8f0 and 4a796e2.

📒 Files selected for processing (8)
  • src/composables/useSSORouting.ts
  • src/pages/login.vue
  • supabase/functions/_backend/private/sso/check-domain.ts
  • supabase/functions/_backend/private/sso/check-enforcement.ts
  • supabase/migrations/20260502134501_restrict_sso_lookup_rpc_access.sql
  • tests/security-definer-execute-hardening.test.ts
  • tests/sso-check-domain-response.unit.test.ts
  • tests/sso.test.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/sso.test.ts (1)

101-110: ⚡ Quick win

Strengthen this regression check with an exact public response shape

This currently checks two fields, but a strict shape assertion will catch any future internal-field leakage in one place.

Suggested test adjustment
-      const data = await response.json() as {
-        has_sso: boolean
-        enforce_sso?: boolean
-        provider_id?: string
-        org_id?: string
-      }
-      expect(data.has_sso).toBe(true)
-      expect(data.enforce_sso).toBe(false)
-      expect(data.provider_id).toBeUndefined()
-      expect(data.org_id).toBeUndefined()
+      const data = await response.json() as {
+        has_sso: boolean
+        enforce_sso: boolean
+      }
+      expect(data).toStrictEqual({
+        has_sso: true,
+        enforce_sso: false,
+      })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/sso.test.ts` around lines 101 - 110, Replace the multiple loose
assertions with a single strict shape assertion on the parsed response object so
any unexpected fields leak will fail the test; specifically, after calling
response.json() (the variable data), assert the entire object equals the exact
public shape (e.g., has_sso: true, enforce_sso: false, provider_id: undefined,
org_id: undefined) using a strict equality matcher like toStrictEqual/toEqual on
the data variable to catch any extra fields.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/sso.test.ts`:
- Around line 101-110: Replace the multiple loose assertions with a single
strict shape assertion on the parsed response object so any unexpected fields
leak will fail the test; specifically, after calling response.json() (the
variable data), assert the entire object equals the exact public shape (e.g.,
has_sso: true, enforce_sso: false, provider_id: undefined, org_id: undefined)
using a strict equality matcher like toStrictEqual/toEqual on the data variable
to catch any extra fields.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2a3cb6e0-8e23-494e-9e81-e4a99ab560a3

📥 Commits

Reviewing files that changed from the base of the PR and between 4a796e2 and a26b81e.

📒 Files selected for processing (2)
  • supabase/functions/_backend/private/sso/check-domain.ts
  • tests/sso.test.ts
💤 Files with no reviewable changes (1)
  • supabase/functions/_backend/private/sso/check-domain.ts

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 4, 2026

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