Skip to content

fix: lock down identity org RPC exposure#1715

Closed
riderx wants to merge 64 commits intomainfrom
riderx/fix-apikey-oracle-ci
Closed

fix: lock down identity org RPC exposure#1715
riderx wants to merge 64 commits intomainfrom
riderx/fix-apikey-oracle-ci

Conversation

@riderx
Copy link
Member

@riderx riderx commented Feb 27, 2026

Summary

  • Added a migration to remove PostgREST-facing access to identity resolution RPCs (get_identity_apikey_only, get_identity_org_allowed, get_identity_org_appid) from anon and authenticated roles.
  • Reworked public.get_orgs_v6(userid uuid) to enforce that callable user IDs match the authenticated caller identity, preventing user-id probing and unauthorized org membership leaks.
  • Tightened execution grants to keep get_orgs_v6(userid uuid) and identity helpers available only to trusted roles and revoked broad default anonymous/authenticated function/table privilege inheritance for new objects.

Test plan

  • Run bun lint.
  • Review git diff origin/main... for the migration scope and ensure no unrelated objects changed.
  • Apply migration in a non-production environment and verify:
    • get_identity_apikey_only/get_identity_org_allowed/get_identity_org_appid are not callable as anon.
    • get_orgs_v6(<other-user>) is denied for non-service roles.

Screenshots

Checklist

  • My code follows the code style of this project and passes
    bun run lint:backend && bun run lint.
  • My change requires a change to the documentation.
  • I have updated the documentation
    accordingly.
  • My change has adequate E2E test coverage.
  • I have tested my code manually, and I have provided steps how to reproduce
    my tests

Summary by CodeRabbit

  • New Features

    • Added email verification requirement for account deletion with notification banner and resend option
    • Introduced 2FA self-enforcement check—users must enable 2FA on their own account before applying organization-wide 2FA policies
    • Added translations for 2FA enforcement and email verification across 15+ languages
  • Security Improvements

    • Restricted API key privilege escalation; limited scope keys cannot create unlimited keys
    • Enhanced role-based access control for organization member management
    • Added email verification gates for sensitive operations
  • Bug Fixes

    • Fixed SQL injection vulnerabilities in analytics queries
    • Improved webhook access restrictions to admin users only
  • Chores

    • Bumped version to 12.116.21; updated Vue and related dependencies to 3.5.29
    • Enhanced read replica password management tooling

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 27, 2026

Warning

Rate limit exceeded

@riderx has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 24 minutes and 54 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 919702c and 02559d3.

📒 Files selected for processing (12)
  • src/types/supabase.types.ts
  • supabase/functions/_backend/utils/supabase.types.ts
  • supabase/migrations/20260302000000_rbac_default_for_new_orgs.sql
  • supabase/migrations/20260302185011_fix_rbac_check_effective_user.sql
  • supabase/schemas/prod.sql
  • supabase/seed.sql
  • supabase/tests/28_test_new_migration_functions.sql
  • supabase/tests/37_test_check_min_rights_2fa_enforcement.sql
  • supabase/tests/40_test_password_policy_enforcement.sql
  • tests/organization-api.test.ts
  • tests/password-policy.test.ts
  • tests/private-error-cases.test.ts
📝 Walkthrough

Walkthrough

This PR implements email verification enforcement, expands 2FA enforcement features, introduces RBAC-based privilege escalation guards, adds read-replica password management tooling, refactors onboarding UI components, and updates multiple database functions with enhanced security checks and row-level security policies.

Changes

Cohort / File(s) Summary
Internationalization
messages/{de,en,es,fr,hi,id,it,ja,ko,pl,pt-br,ru,tr,vi,zh-cn}.json
Added translation keys for 2FA enforcement self-requirement message across all locales; added English banner and destination labels for email verification flows.
Configuration & Versioning
.gitsecret/paths/mapping.cfg, package.json, supabase/functions/_backend/utils/version.ts
Updated encrypted credential mapping hash and bumped version from 12.116.10 to 12.116.21; upgraded Vue and related compiler/renderer from 3.5.28 to 3.5.29.
Authentication & Email Verification
src/modules/auth.ts, src/pages/resend_email.vue
Introduced email verification gate that redirects unauthenticated users with unconfirmed emails to resend_email flow with reason and return path; added route-based UI logic to display verification banner with optional destination context.
Account Management
src/pages/delete_account.vue, src/pages/settings/organization/Security.vue
Added email verification check before account deletion with loading state and error messaging; added pre-check in 2FA enforcement toggle to verify current user has an active 2FA factor before allowing org-wide enforcement.
Onboarding Components
src/components/dashboard/DemoOnboardingGate.vue, src/components/dashboard/DemoOnboardingModal.vue
Simplified gate logic to rely solely on route query parameters instead of Pinia/Supabase state; refactored modal layout with max-height constraint, overflow scrolling, and responsive grid restructuring for app choices and UI elements.
Internationalization Configuration
src/modules/i18n.ts
Added fallback locale setting to English when translations are missing.
Read Replica Management
read_replicate/update_readreplica_passwords.sh
New 279-line Bash script for discovering and updating read-replica subscription passwords across multiple regions, with environment validation, parallel processing, error handling, and cleanup logic.
API Key & Build System
supabase/functions/_backend/public/apikey/post.ts, supabase/functions/_backend/public/build/{request,upload}.ts
Enhanced API key creation to prevent unlimited keys from limited callers; introduced buildBuilderPayload utility to structure builder requests with build options/credentials; replaced simpleError with quickError for consistency.
RBAC & Privilege Checks
supabase/functions/_backend/private/role_bindings.ts
Added getCallerMaxPriorityRank helper to compute caller's highest privilege; enforced privilege escalation guards on POST/PATCH/DELETE of role bindings to prevent assigning roles with higher priority than caller's own.
Organization Member Management
supabase/functions/_backend/public/organization/members/delete.ts
Added cleanup of role_bindings when deleting organization members via admin client to prevent orphaned RBAC records.
Database Utilities
supabase/functions/_backend/utils/{cloudflare,supabase}.ts
Introduced escapeSqlString helper and replaced direct SQL interpolations with escaped values across Cloudflare Analytics queries; updated channel upsert logic to preserve created_by field during updates.
Database Migrations - Security & Access Control
supabase/migrations/20250530233128_base.sql, supabase/migrations/2026022[567]*.sql
Comprehensive security hardening: revoked anonymous access from oracle/identity RPCs; introduced new SECURITY DEFINER functions (delete_user with email/reauthentication enforcement, get_orgs_v6 with redaction logic, invite_user_to_org with access checks, rescind_invitation, record_build_time, rbac_check_permission_direct with hashed API key support); updated RLS policies for webhooks and role_bindings; added triggers to prevent deleting last super_admin binding.
Database Tests
supabase/tests/{28,34,35}_test*.sql, tests/{builder-payload.unit,organization-api}.test.ts
Added rescind_invitation test cases; converted role_bindings mutation test to read-only verification; added platform_super_admin binding bypass for RBAC tests; added unit test for buildBuilderPayload snake_case to camelCase conversion; added assertions verifying role_bindings trigger creation and cleanup on org member operations.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~110 minutes

Possibly related PRs

Suggested labels

💰 Rewarded, 🔐 Security, 🗄️ Database

Poem

🐰 A rabbit hops through verified gates,
Where 2FA enforcement awaits,
RBAC guards each privilege tight,
Translations bloom in languages bright,
Email checks and read-replicas take flight! 🚀

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.03% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly describes the main security objective: locking down (restricting) access to identity and organization RPCs. This aligns with the core changes removing PostgREST access and tightening execution grants.
Description check ✅ Passed The PR description includes all required template sections: a clear summary of changes, a detailed test plan with specific verification steps, and a partially completed checklist. The description comprehensively explains the security fixes and provides actionable testing guidance.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch riderx/fix-apikey-oracle-ci

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.

Copy link

@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: 5960acaf24

ℹ️ 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 +5 to +6
REVOKE ALL ON FUNCTION "public"."get_identity_apikey_only" ("keymode" "public"."key_mode"[]) FROM "anon";
REVOKE ALL ON FUNCTION "public"."get_identity_apikey_only" ("keymode" "public"."key_mode"[]) FROM "authenticated";

Choose a reason for hiding this comment

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

P1 Badge Revoke PUBLIC execute on identity helper functions

Revoking these RPCs from anon/authenticated is not sufficient to block direct calls because PostgreSQL grants EXECUTE on functions to PUBLIC by default, and both API roles inherit PUBLIC. As written, callers can still invoke get_identity_apikey_only (and the other identity helpers) through that inherited grant, so the identity-oracle hardening is bypassed unless you also REVOKE ... FROM PUBLIC before re-granting trusted roles.

Useful? React with 👍 / 👎.

Comment on lines +37 to +38
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" REVOKE ALL ON FUNCTIONS FROM "anon";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" REVOKE ALL ON FUNCTIONS FROM "authenticated";

Choose a reason for hiding this comment

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

P2 Badge Revoke PUBLIC default execute for future functions

These default-privilege changes only remove future grants for anon/authenticated, but they leave the default PUBLIC function execute privilege untouched. New functions created by postgres in public will therefore still be executable by API roles via inherited PUBLIC, which undermines the stated goal that future objects should not inherit anonymous/authenticated function access.

Useful? React with 👍 / 👎.

riderx added 26 commits March 2, 2026 18:08
riderx added 28 commits March 3, 2026 15:51
@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 3, 2026

@riderx riderx closed this Mar 3, 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