Skip to content

fix(backend): prevent org existence oracle#1613

Merged
riderx merged 2 commits intomainfrom
riderx/validate-org-oracle
Feb 10, 2026
Merged

fix(backend): prevent org existence oracle#1613
riderx merged 2 commits intomainfrom
riderx/validate-org-oracle

Conversation

@riderx
Copy link
Copy Markdown
Member

@riderx riderx commented Feb 10, 2026

Summary (AI generated)

  • Prevent org existence probing via /private/validate_password_compliance by authenticating first and returning a stable not_member for non-members/non-existent orgs.
  • Keep remediation working for password-policy non-compliant users by fetching org policy with service-role after membership verification (avoids check_min_rights password-policy enforcement loop).

Motivation (AI generated)

/private/validate_password_compliance leaked org existence via status/error differences and must remain usable as the password-policy remediation path.

Business Impact (AI generated)

Reduces org enumeration risk without breaking the password-policy compliance flow for legitimate users.

Test Plan (AI generated)

  • bun lint:backend && bun lint
  • bunx supabase db reset
  • SUPABASE_URL=http://127.0.0.1:54321 SUPABASE_ANON_KEY=<from bunx supabase status --output env> bun run test:backend -- tests/password-policy.test.ts

Generated with AI

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Password policy validation now enforces user authentication before verifying organization membership and retrieving policies.
    • Error responses improved to provide more specific feedback and prevent disclosing organization existence information.
  • Tests

    • Updated test cases to validate new authentication flow and error handling behavior.

Copilot AI review requested due to automatic review settings February 10, 2026 13:00
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 46729ddb09

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 124 to 128
const { data: org, error: orgError } = await userClient
.from('orgs')
.select('id, password_policy_config')
.eq('id', body.org_id)
.single()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Fetch org policy without password-policy RLS

The new userClient.from('orgs').select(...).single() lookup runs under normal org RLS, but org SELECT uses check_min_rights (supabase/schemas/prod.sql line 14619), and check_min_rights enforces password-policy compliance (supabase/schemas/prod.sql lines 1331-1343). That means a valid member who is currently non-compliant (the exact user this endpoint is meant to help) cannot read the org row, hits this branch, and gets 403 not_member instead of password_does_not_meet_policy, so they cannot complete the remediation flow. This undoes the purpose of rbac_check_permission_no_password_policy introduced in supabase/migrations/20260201042609_fix_password_policy_org_read_gate.sql.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens the /private/validate_password_compliance endpoint against organization existence probing by authenticating first and normalizing responses for unknown/non-member orgs.

Changes:

  • Authenticate before any org lookup and return stable not_member responses for unknown/non-member org IDs.
  • Switch org policy lookup to use an authenticated Supabase client (instead of service-role) and keep compliance upsert via service-role.
  • Update/add Vitest coverage to ensure invalid credentials do not reveal org existence.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
tests/password-policy.test.ts Updates expectations for non-existent orgs and adds a regression test ensuring invalid credentials don’t reveal org existence.
supabase/functions/_backend/private/validate_password_compliance.ts Reorders flow to authenticate first and normalizes org-not-found vs non-member responses to avoid an existence oracle.

Comment on lines 123 to 129
// Fetch the org's password policy (member-only).
const { data: org, error: orgError } = await userClient
.from('orgs')
.select('id, password_policy_config')
.eq('id', body.org_id)
.single()

Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

The org password policy lookup is now done with userClient (RLS enforced). orgs SELECT is guarded by check_min_rights, which enforces user_meets_password_policy (and 2FA), so a user who is currently non-compliant may be unable to read org.password_policy_config and will get not_member, creating a circular dependency (they can’t validate to become compliant). Fetch the org’s policy using the service-role adminClient after the membership check, or expose a dedicated SECURITY DEFINER/RPC to read just the policy config for verified members without enforcing password policy.

Copilot uses AI. Check for mistakes.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 10, 2026

📝 Walkthrough

Walkthrough

Authentication-first flow: sign in with user credentials, create a per-user client, verify org membership, then fetch org password policy and upsert user compliance; error codes and test expectations updated accordingly. (49 words)

Changes

Cohort / File(s) Summary
Backend Function
supabase/functions/_backend/private/validate_password_compliance.ts
Reworks admin-only flow to an authentication-first flow: sign-in → per-user client → org membership check (checkOrgReadAccess) → fetch org's password_policy_config → validate policy and compute policy hash → upsert user_password_compliance via admin client. Adds/changes error codes (invalid_credentials, org_membership_lookup_failed, not_member, hash_failed, compliance_update_failed) and logging; replaces some 404s with 403/500 on lookup failures.
Test Suite
tests/password-policy.test.ts
Updates tests to use USER_EMAIL/USER_PASSWORD in request bodies, changes expectations for non-member/org-not-found from 404 org_not_found → 403 not_member, adds tests for invalid credentials returning 401 invalid_credentials, and adds assertion for structured policy validation errors (400 with moreInfo.errors).

Sequence Diagram

sequenceDiagram
    participant Client
    participant Auth as Auth/Session
    participant UserClient as User Client
    participant OrgDB as Organization DB
    participant AdminClient as Admin Client

    Client->>Auth: Sign in (email/password)
    alt invalid credentials
        Auth-->>Client: 401 (invalid_credentials)
    else valid credentials
        Auth-->>UserClient: Session / user token
        UserClient->>OrgDB: checkOrgReadAccess(org_id)
        alt not a member / lookup failed
            OrgDB-->>UserClient: not_member / error
            UserClient-->>Client: 403 (not_member) or 500 (org_membership_lookup_failed)
        else is member
            UserClient->>OrgDB: fetch password_policy_config(org_id)
            OrgDB-->>UserClient: policy_config
            UserClient->>UserClient: validate password against policy, compute policy hash
            UserClient-->>AdminClient: request upsert compliance (user_id, org_id, hash, result)
            AdminClient->>OrgDB: upsert user_password_compliance
            OrgDB-->>AdminClient: upsert result
            AdminClient-->>Client: 200 (success) or 500 (compliance_update_failed)
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped in with credentials bright,
I checked the org by soft moonlight,
Policies found and hashes spun,
Compliance upserted — work well done! 🥕✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main security fix: preventing organization existence enumeration (oracle) via the validate_password_compliance endpoint.
Description check ✅ Passed The description includes a summary explaining the motivation and business impact, and provides a detailed test plan with specific commands. However, the description lacks proper formatting with the required template sections and is missing checklist items.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch riderx/validate-org-oracle

No actionable comments were generated in the recent review. 🎉


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@riderx riderx force-pushed the riderx/validate-org-oracle branch from 5cfa399 to 7b0192f Compare February 10, 2026 13:15
@sonarqubecloud
Copy link
Copy Markdown

@riderx riderx merged commit 482346b into main Feb 10, 2026
11 checks passed
@riderx riderx deleted the riderx/validate-org-oracle branch February 10, 2026 13:43
@riderx
Copy link
Copy Markdown
Member Author

riderx commented Feb 10, 2026

/tip @Judel777 $100

@algora-pbc
Copy link
Copy Markdown

algora-pbc bot commented Feb 10, 2026

🎉🎈 @Judel777 has been awarded $100 by Capgo! 🎈🎊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants