Skip to content

fix: revoke public execute from API key helper RPCs#1965

Merged
riderx merged 8 commits into
mainfrom
codex/fix-ghsa-7r6g-whg3-5mm4
Apr 27, 2026
Merged

fix: revoke public execute from API key helper RPCs#1965
riderx merged 8 commits into
mainfrom
codex/fix-ghsa-7r6g-whg3-5mm4

Conversation

@riderx
Copy link
Copy Markdown
Member

@riderx riderx commented Apr 27, 2026

Summary (AI generated)

  • Revoke PUBLIC execute access from public.get_user_id(...) and public.get_org_perm_for_apikey(...)
  • Re-grant execute only to authenticated and service_role so anon no longer inherits access implicitly
  • Add a pgTAP regression that checks function ACLs directly to prevent the same privilege mistake from returning

Motivation (AI generated)

The previous hardening migrations revoked these helper RPCs from anon, but did not revoke them from PUBLIC. In PostgreSQL, new functions are executable by PUBLIC by default, and anon inherits that privilege, so the original mitigation did not actually remove anonymous access. This change closes the advisory by fixing the real ACL root cause and adding a regression test for it.

Compatibility note: the current public CLI still calls these RPCs through the public Supabase client. This PR intentionally closes the server-side oracle in Capgo first; CLI rollout needs to be coordinated before deployment.

Business Impact (AI generated)

This removes an unauthenticated API-key validity and permission oracle from the public Supabase surface, which reduces the blast radius of leaked keys and prevents external user/org/app enumeration. It improves customer trust and lowers the risk of follow-on abuse using exposed metadata.

Test Plan (AI generated)

  • bun run lint:sql -- supabase/migrations/20260427105909_fix_apikey_helper_rpc_public_execute.sql supabase/tests/49_test_apikey_oracle_rpc_permissions.sql
  • bunx supabase test db supabase/tests/10_utility_functions.sql supabase/tests/14_test_apikey.sql supabase/tests/49_test_apikey_oracle_rpc_permissions.sql --local --workdir /Users/martindonadieu/.codex/worktrees/635c/capgo/.context/supabase-worktrees/3eee24d7
  • Validate coordinated CLI rollout before production deployment

Generated with AI

Summary by CodeRabbit

  • Security

    • Restricted API key access permissions to authenticated users and service roles only, enhancing security boundaries.
    • Implemented improved API key validation and authorization checks for app storage operations.
  • Tests

    • Added comprehensive tests for API key permission enforcement and authorization flows.
    • Refactored test utilities to support centralized API key validation and authentication.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 27, 2026

Warning

Rate limit exceeded

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

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ 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.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: df3887f7-39b7-4180-907d-d4078b262ea9

📥 Commits

Reviewing files that changed from the base of the PR and between edfac66 and e1dfb20.

📒 Files selected for processing (4)
  • tests/cli-new-encryption.test.ts
  • tests/cli-sdk-utils.ts
  • tests/files-security.test.ts
  • tests/updates.test.ts
📝 Walkthrough

Walkthrough

This PR restricts API-key RPC access by revoking PUBLIC execute permissions from three functions and re-granting only to AUTHENTICATED and SERVICE_ROLE roles. It introduces a new capgo_private schema with a SECURITY DEFINER helper function that validates API key identity from request headers, checks expiration and ownership, then updates Supabase Storage policies to authorize bucket access via the new helper with appropriate key mode constraints.

Changes

Cohort / File(s) Summary
API Key Authorization
supabase/migrations/20260427105909_fix_apikey_helper_rpc_public_execute.sql
New capgo_private schema with SECURITY DEFINER helper function matches_app_storage_apikey_owner(...) for validating API key identity from request headers; revokes PUBLIC execute on public.get_user_id(text), public.get_user_id(text, text), and public.get_org_perm_for_apikey(text, text), re-grants to AUTHENTICATED and SERVICE_ROLE; updates Supabase Storage policies on apps bucket to authorize access via API keys with mode/expiration/ownership validation.
Permission and Identity Tests
supabase/tests/49_test_apikey_oracle_rpc_permissions.sql, supabase/tests/07_auth_functions.sql, supabase/tests/19_test_identity_functions.sql
New comprehensive permission test for RPC execute privileges across roles; adds explicit authentication setup/teardown in identity function tests to ensure correct user context during API key validation assertions.
Test Utilities and SDK
tests/cli-sdk-utils.ts, tests/cli-hashed-apikey.test.ts
Major refactoring of test SDK utilities to support Supabase-backed authorization: fetches app/channel/version data, validates API keys via RPC, enforces key mode/org/app restrictions, builds bundle zips with SHA-256 checksums and AES-128-CBC encryption, manages signed URLs for storage uploads, and creates app_versions records; replaces manual SDK instantiation with centralized createTestSDK() factory.
Test Setup Refactoring
tests/cli-channel.test.ts
Replaces CLI SDK helper workflow with direct database seeding of bundle versions; generates dynamic bundle identifiers per test run and inserts app_versions rows with required ownership/storage provider fields.

Sequence Diagram

sequenceDiagram
    actor Client
    participant RPC as Public RPC<br/>(get_user_id)
    participant Helper as capgo_private Helper<br/>(SECURITY DEFINER)
    participant DB as Database
    participant Storage as Storage Bucket<br/>(apps)

    Client->>RPC: call get_user_id() or<br/>get_org_perm_for_apikey()
    Note over RPC: Only AUTHENTICATED<br/>or SERVICE_ROLE allowed
    
    Client->>Storage: DELETE/UPDATE/INSERT/SELECT<br/>request + capgkey header
    Storage->>Helper: invoke matches_app_storage_apikey_owner()<br/>with (folder_user_id, app_id, key_modes)
    
    Helper->>DB: extract capgkey from<br/>request.headers
    Helper->>DB: lookup API key record<br/>by value hash
    
    alt Key exists & valid
        Helper->>DB: check key expiration<br/>& mode compatibility
        Helper->>DB: verify app/folder<br/>ownership constraints
        Helper-->>Storage: return TRUE
        Storage-->>Client: grant access
    else Invalid/expired/insufficient perms
        Helper-->>Storage: return FALSE
        Storage-->>Client: deny access
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 Hop! The keys now guard their gates with care,
With private helpers checking everywhere,
Expiration dates and ownership locks align,
No more public secrets—each RPC now divine! ✨🔐

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.52% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description includes a comprehensive summary, motivation, business impact, and test plan with specific test commands executed. However, it does not follow the provided repository template structure (missing sections: Test plan details, Screenshots, Checklist). Consider structuring the description to match the repository template with explicit sections for Summary, Test plan with reproduction steps, Screenshots (if applicable), and a completed Checklist for code style, documentation, tests, and manual testing confirmation.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main security change: revoking public execute permissions from API key helper RPCs, which is the core fix in this pull request.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-ghsa-7r6g-whg3-5mm4

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

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented Apr 27, 2026

Merging this PR will not alter performance

✅ 28 untouched benchmarks


Comparing codex/fix-ghsa-7r6g-whg3-5mm4 (e1dfb20) with main (8be5843)

Open in CodSpeed

Comment thread tests/cli-sdk-utils.ts Fixed
@riderx riderx marked this pull request as ready for review April 27, 2026 14:21
@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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/cli-sdk-utils.ts`:
- Around line 770-829: The code creates the DB record via createBundleRecord
before calling uploadBufferToStorage, so if uploadBufferToStorage fails the
app_versions row (versionId) is left pointing to a missing blob; modify the flow
to ensure cleanup: after calling createBundleRecord(store the returned
versionId) wrap uploadBufferToStorage in a try/catch (or add cleanup in the
outer catch) and on any upload error delete the created DB row (use the same
identifier versionId and existing DB client pattern used elsewhere, e.g.
getSupabaseClient().from('app_versions').delete().eq('id', versionId) or a
deleteBundleRecord helper) before returning the failure result; ensure this runs
only when versionId was set so you don’t delete unrelated rows.
- Around line 493-509: The encrypted branch returns a sessionKey but omits the
required key_id, causing DB inserts to fail for encrypted bundles; update the
code that builds the return object (where sessionKey / session_key and
encryptedSessionKey are set) to also supply key_id (e.g., derive from
options.encryptionKey or accept an explicit options.encryptionKeyId) and include
it in the returned payload as key_id so the inserted app_versions row matches
the encrypted-bundle shape expected by the DB. Ensure the symbol names match the
DB field (key_id) and use the same source of truth as the encryption key
(options.encryptionKey or a new options.encryptionKeyId) when constructing the
returned object.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 61a21421-7993-4b50-98aa-d8ecf6c35a55

📥 Commits

Reviewing files that changed from the base of the PR and between 3095cf1 and edfac66.

📒 Files selected for processing (7)
  • supabase/migrations/20260427105909_fix_apikey_helper_rpc_public_execute.sql
  • supabase/tests/07_auth_functions.sql
  • supabase/tests/19_test_identity_functions.sql
  • supabase/tests/49_test_apikey_oracle_rpc_permissions.sql
  • tests/cli-channel.test.ts
  • tests/cli-hashed-apikey.test.ts
  • tests/cli-sdk-utils.ts

Comment thread tests/cli-sdk-utils.ts
Comment thread tests/cli-sdk-utils.ts Outdated
@sonarqubecloud
Copy link
Copy Markdown

@riderx riderx merged commit 1a2e89c into main Apr 27, 2026
16 checks passed
@riderx riderx deleted the codex/fix-ghsa-7r6g-whg3-5mm4 branch April 27, 2026 15:44
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.

2 participants