Skip to content

Comments

fix(security): revoke anon access to apikey oracle RPCs#1670

Merged
riderx merged 11 commits intomainfrom
riderx/fix-sb-rpc-oracles
Feb 25, 2026
Merged

fix(security): revoke anon access to apikey oracle RPCs#1670
riderx merged 11 commits intomainfrom
riderx/fix-sb-rpc-oracles

Conversation

@riderx
Copy link
Member

@riderx riderx commented Feb 24, 2026

Summary (AI generated)

  • Added migration 20260224130000_restrict_rpc_api_key_oracles.sql to revoke anonymous execution on API key oracle RPCs.
  • Removed anonymous-facing oracle RPC calls from the internal upload/delete handlers so the security hardening does not break private upload flows:
    • supabase/functions/_backend/private/upload_link.ts
    • supabase/functions/_backend/private/delete_failed_version.ts
  • Kept SECURITY DEFINER behavior for authenticated contexts while removing anonymous access to:
    • public.get_user_id(apikey text)
    • public.get_user_id(apikey text, app_id text)
    • public.get_org_perm_for_apikey(apikey text, app_id text).

Motivation (AI generated)

  • Prevent leaked sb_publishable_* keys from being used as validation oracles while preserving expected behavior for authenticated internal API-key requests.

Business Impact (AI generated)

  • Reduces key-leak blast radius and prevents user/app/permission inference from unauthenticated RPC probes.
  • Avoids regressions in private upload flows that rely on API-key middleware context.

Test Plan (AI generated)

  • bun lint
  • bun lint:backend
  • Confirmed internal private upload/delete handlers no longer call rpc('get_user_id', { apikey, app_id }) via supabaseApikey client.
  • Execute a PostgREST PoC with a valid publishable key and invalid/unknown key to validate get_user_id / get_org_perm_for_apikey now return permission errors for anon (requires local/remote Supabase runtime)
  • Execute full regression path for /private/upload_link and /private/delete_failed_version against a seeded API key in integration environment

Generated with AI

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 24, 2026

Warning

Rate limit exceeded

@riderx has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 27 minutes and 40 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 b410899 and e54ffc2.

📒 Files selected for processing (10)
  • package.json
  • src/pages/admin/dashboard/replication.vue
  • supabase/functions/_backend/files/preview.ts
  • supabase/functions/_backend/private/delete_failed_version.ts
  • supabase/functions/_backend/private/upload_link.ts
  • supabase/functions/_backend/public/build/index.ts
  • supabase/functions/_backend/public/replication.ts
  • supabase/functions/_backend/utils/version.ts
  • supabase/migrations/20260224100000_fix_webhook_rls_org_scoping.sql
  • tests/build-upload-head-routing.test.ts
📝 Walkthrough

Walkthrough

A SQL migration is added that revokes anonymous execution permissions on three RPC functions—public.get_user_id() with two signatures and public.get_org_perm_for_apikey()—preventing unauthenticated users from executing these API key validation functions.

Changes

Cohort / File(s) Summary
Database Migration
supabase/migrations/20260224130000_restrict_rpc_api_key_oracles.sql
Revokes ALL permissions on three API key validation RPCs from the anon role to restrict access to authenticated users only.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

Possibly related PRs

Suggested labels

💰 Rewarded

Poem

🐰 A rabbit hops through databases deep,
Revoking secrets the anon can't keep,
Three functions locked with a careful hand,
Authentication is now the command!

🚥 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: revoking anonymous access to API key oracle RPCs, which matches the core change in the migration file.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed PR description includes all required template sections: Summary, Test plan, and Checklist with comprehensive details about security changes, motivation, and verification steps.

✏️ 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-sb-rpc-oracles

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: b410899d18

ℹ️ 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".

@@ -0,0 +1,4 @@
-- Revoke anonymous execution of key-validation RPCs to prevent unauthenticated oracles
REVOKE ALL ON FUNCTION "public"."get_user_id" ("apikey" "text") FROM "anon";
REVOKE ALL ON FUNCTION "public"."get_user_id" ("apikey" "text", "app_id" "text") FROM "anon";

Choose a reason for hiding this comment

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

P1 Badge Preserve get_user_id RPC for anon-backed key flows

Revoking anon execute on get_user_id(apikey, app_id) breaks existing API-key request paths that still call this RPC via supabaseApikey(...) (which uses SUPABASE_ANON_KEY in supabase/functions/_backend/utils/supabase.ts). Both supabase/functions/_backend/private/upload_link.ts:33 and supabase/functions/_backend/private/delete_failed_version.ts:33 call this function before continuing, so after this migration they receive a permission error and return user_not_found, blocking those upload/delete flows for valid keys.

Useful? React with 👍 / 👎.

riderx and others added 10 commits February 24, 2026 23:27
* fix(build): handle tus HEAD upload route

* fix(build): chain HEAD middleware correctly
* fix(security): protect replication endpoint

* fix(api): require replication endpoint internal api secret

* fix(api): allow admin JWT access to replication endpoint

* fix(frontend): use admin session only when no replication secret
* fix(backend): use exact app_id match for preview lookup

* fix(backend): preserve case-insensitive preview app lookup
@sonarqubecloud
Copy link

@riderx riderx merged commit 3f6a2e5 into main Feb 25, 2026
13 of 14 checks passed
@riderx riderx deleted the riderx/fix-sb-rpc-oracles branch February 25, 2026 04:29
riderx added a commit that referenced this pull request Feb 25, 2026
* fix(security): revoke anon access to exist_app_v2 rpc

* fix(build): restore TUS HEAD upload routing (#1664)

* fix(build): handle tus HEAD upload route

* fix(build): chain HEAD middleware correctly

* chore(release): 12.116.2

* fix(security): protect replication endpoint (#1686)

* fix(security): protect replication endpoint

* fix(api): require replication endpoint internal api secret

* fix(api): allow admin JWT access to replication endpoint

* fix(frontend): use admin session only when no replication secret

* fix(security): revoke PUBLIC execute on exist_app_v2 rpc

* fix(security): revoke anon execute on exist_app_v2 rpc

* fix(database): enforce org-scoped webhook rls (#1676)

* fix: use exact app_id match for preview lookup (#1674)

* fix(backend): use exact app_id match for preview lookup

* fix(backend): preserve case-insensitive preview app lookup

* chore(release): 12.116.3

* fix(security): revoke anon access to exist_app_v2 rpc

* fix(security): revoke PUBLIC execute on exist_app_v2 rpc

* fix(security): revoke anon execute on exist_app_v2 rpc

* fix(frontend): require confirmation before URL login session (#1688)

* fix(frontend): require confirmation for URL session login

* fix(build): restore TUS HEAD upload routing (#1664)

* fix(build): handle tus HEAD upload route

* fix(build): chain HEAD middleware correctly

* chore(release): 12.116.2

* fix(security): protect replication endpoint (#1686)

* fix(security): protect replication endpoint

* fix(api): require replication endpoint internal api secret

* fix(api): allow admin JWT access to replication endpoint

* fix(frontend): use admin session only when no replication secret

* fix(frontend): retain tokens until query login succeeds

* fix(database): enforce org-scoped webhook rls (#1676)

* fix: use exact app_id match for preview lookup (#1674)

* fix(backend): use exact app_id match for preview lookup

* fix(backend): preserve case-insensitive preview app lookup

* chore(release): 12.116.3

* fix(frontend): require confirmation for URL session login

* fix(frontend): retain tokens until query login succeeds

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* chore(release): 12.116.4

* Riderx/fix email otp rpc reopen (#1693)

* fix(security): restrict email otp verification rpc path

* fix(security): also revoke otp rpc execute from public

* fix(security): record email otp verification via service-side rpc

* fix(security): harden email otp verification RPC usage

* fix(db): drop legacy record_email_otp_verified overload

* fix(frontend): delete replaced profile images from storage (#1683)

* fix(frontend): delete replaced profile images from storage

* fix(backend): clean stale unlinked user avatars

* fix(build): restore TUS HEAD upload routing (#1664)

* fix(build): handle tus HEAD upload route

* fix(build): chain HEAD middleware correctly

* chore(release): 12.116.2

* fix(security): protect replication endpoint (#1686)

* fix(security): protect replication endpoint

* fix(api): require replication endpoint internal api secret

* fix(api): allow admin JWT access to replication endpoint

* fix(frontend): use admin session only when no replication secret

* fix: address sonar regex exec suggestions

* fix(database): enforce org-scoped webhook rls (#1676)

* fix: use exact app_id match for preview lookup (#1674)

* fix(backend): use exact app_id match for preview lookup

* fix(backend): preserve case-insensitive preview app lookup

* chore(release): 12.116.3

* fix(frontend): delete replaced profile images from storage

* fix(backend): clean stale unlinked user avatars

* fix: address sonar regex exec suggestions

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* fix: restrict find_apikey_by_value RPC to service role (#1672)

* fix(security): restrict find_apikey_by_value to service role

* fix(build): restore TUS HEAD upload routing (#1664)

* fix(build): handle tus HEAD upload route

* fix(build): chain HEAD middleware correctly

* chore(release): 12.116.2

* fix(security): protect replication endpoint (#1686)

* fix(security): protect replication endpoint

* fix(api): require replication endpoint internal api secret

* fix(api): allow admin JWT access to replication endpoint

* fix(frontend): use admin session only when no replication secret

* fix(database): enforce org-scoped webhook rls (#1676)

* fix: use exact app_id match for preview lookup (#1674)

* fix(backend): use exact app_id match for preview lookup

* fix(backend): preserve case-insensitive preview app lookup

* chore(release): 12.116.3

* fix(security): restrict find_apikey_by_value to service role

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* fix: secure get_total_metrics rpc (#1671)

* fix(db): harden get_total_metrics rpc auth

* fix(db): qualify org_id and harden rpc role checks

* fix(db): align get_total_metrics auth overloads

* fix(db): harden get_total_metrics rpc auth

* fix(db): qualify org_id and harden rpc role checks

* fix(db): align get_total_metrics auth overloads

* fix(db): harden get_total_metrics rpc auth

* fix(db): qualify org_id and harden rpc role checks

* fix(db): align get_total_metrics auth overloads

* fix(backend): validate stripe redirect URLs (#1681)

* fix(backend): validate stripe redirect URLs

* fix(build): restore TUS HEAD upload routing (#1664)

* fix(build): handle tus HEAD upload route

* fix(build): chain HEAD middleware correctly

* chore(release): 12.116.2

* fix(security): protect replication endpoint (#1686)

* fix(security): protect replication endpoint

* fix(api): require replication endpoint internal api secret

* fix(api): allow admin JWT access to replication endpoint

* fix(frontend): use admin session only when no replication secret

* test(backend): add stripe redirect validation tests

* test(backend): fix stripe redirect unit test env setup

* fix(database): enforce org-scoped webhook rls (#1676)

* fix: use exact app_id match for preview lookup (#1674)

* fix(backend): use exact app_id match for preview lookup

* fix(backend): preserve case-insensitive preview app lookup

* chore(release): 12.116.3

* fix(backend): validate stripe redirect URLs

* test(backend): add stripe redirect validation tests

* test(backend): fix stripe redirect unit test env setup

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* feat(api): auto cleanup EXIF image metadata (#1673)

* feat(api): auto cleanup image metadata on updates

* fix: preserve content type when stripping image metadata

* fix(security): restrict get_orgs_v6(userid uuid) access (#1677)

* fix(security): restrict get_orgs_v6(uuid) execution to private roles

* fix(build): restore TUS HEAD upload routing (#1664)

* fix(build): handle tus HEAD upload route

* fix(build): chain HEAD middleware correctly

* chore(release): 12.116.2

* fix(security): protect replication endpoint (#1686)

* fix(security): protect replication endpoint

* fix(api): require replication endpoint internal api secret

* fix(api): allow admin JWT access to replication endpoint

* fix(frontend): use admin session only when no replication secret

* fix(database): enforce org-scoped webhook rls (#1676)

* fix: use exact app_id match for preview lookup (#1674)

* fix(backend): use exact app_id match for preview lookup

* fix(backend): preserve case-insensitive preview app lookup

* chore(release): 12.116.3

* fix(security): restrict get_orgs_v6(uuid) execution to private roles

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* fix(security): revoke anon access to apikey oracle RPCs (#1670)

* fix(security): restrict apikey oracle rpc execution

* fix(build): restore TUS HEAD upload routing (#1664)

* fix(build): handle tus HEAD upload route

* fix(build): chain HEAD middleware correctly

* chore(release): 12.116.2

* fix(security): protect replication endpoint (#1686)

* fix(security): protect replication endpoint

* fix(api): require replication endpoint internal api secret

* fix(api): allow admin JWT access to replication endpoint

* fix(frontend): use admin session only when no replication secret

* fix: remove anon-backed get_user_id calls in private apikey flows

* fix(database): enforce org-scoped webhook rls (#1676)

* fix: use exact app_id match for preview lookup (#1674)

* fix(backend): use exact app_id match for preview lookup

* fix(backend): preserve case-insensitive preview app lookup

* chore(release): 12.116.3

* fix(security): restrict apikey oracle rpc execution

* fix: remove anon-backed get_user_id calls in private apikey flows

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* fix(security): require capgkey auth in exist_app_v2

* fix(api): block scoped apikey key creation (#1685)

* fix(api): block scoped apikeys from creating keys

* fix(build): restore TUS HEAD upload routing (#1664)

* fix(build): handle tus HEAD upload route

* fix(build): chain HEAD middleware correctly

* chore(release): 12.116.2

* fix(security): protect replication endpoint (#1686)

* fix(security): protect replication endpoint

* fix(api): require replication endpoint internal api secret

* fix(api): allow admin JWT access to replication endpoint

* fix(frontend): use admin session only when no replication secret

* fix(database): enforce org-scoped webhook rls (#1676)

* test: fix apikey test lint violations

* fix: use exact app_id match for preview lookup (#1674)

* fix(backend): use exact app_id match for preview lookup

* fix(backend): preserve case-insensitive preview app lookup

* chore(release): 12.116.3

* fix(api): block scoped apikeys from creating keys

* test: fix apikey test lint violations

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* fix: restrict webhook secret access to admin-only (#1692)

* fix(security): restrict webhook secret read access

* fix(rls): restrict webhook reads to admins

* fix(security): keep only apikey-based exist_app_v2 check

* fix(security): require capgkey auth in exist_app_v2

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
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