-
-
Notifications
You must be signed in to change notification settings - Fork 135
fix(db): revoke remaining anon oracle RPC execute grants #3280
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
riderx
wants to merge
22
commits into
main
Choose a base branch
from
cursor/revoke-anon-oracle-rpc-execute-5117
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
5322603
fix(db): revoke remaining anon oracle RPC execute grants
cursoragent 045b3f1
chore(ci): retrigger workflow after Cloudflare Workers startup flake
cursoragent 3769895
chore(ci): retrigger after backend shard 2 edge 502 flake
cursoragent a1dbc80
test: retry edge 502 flakes in app and cron_stat_org shards
cursoragent 0b52ce5
test: add retryUnsafe to remaining cron_stat_org POST calls
cursoragent 728e290
chore(ci): retrigger after runner cancel and playwright startup flake
cursoragent 623ba93
test: retry POST /apikey 502 flakes in apikeys shard
cursoragent afe8213
test: drop non-idempotent retryUnsafe; assert auth execute on revoked…
TorichanCapgo afe9d2e
fix(db): ORG_NOT_FOUND for internal missing org on member helpers
TorichanCapgo cac5528
chore(schema): sync prod.sql with oracle RPC migration bodies
cursoragent 27a4f2e
test(security): reject OK in missing-invite oracle assertions
cursoragent 7dbb549
style(db): wrap long REVOKE/GRANT lines for SQLFluff LT05
cursoragent 1ae3639
test(apikeys): harden POST /apikey against cold-isolate 502 flakes
cursoragent 244593c
test(apikeys): abort hung POST /apikey fetches at deadline
cursoragent b610745
chore(ci): re-trigger CodeRabbit review on 244593c fixes
cursoragent 6589af2
test(apikeys): abort cleanup fetches at postApiKey deadline
cursoragent c521f54
test(apikeys): keep abort budget through response body reads
cursoragent b98aae9
test(apikeys): propagate abort during 502 body read
cursoragent 473ec4f
chore(ci): retrigger after edge 502 flake on PR workflow shard 6/6
cursoragent 6fcd9f2
test(apikeys): require deadline in deleteApiKeysByName cleanup
cursoragent 61f009b
chore(ci): retrigger after plugin serial 502 flake
cursoragent 708114a
test(apikeys): cap retry delay and bound POST warmup by deadline
cursoragent File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
168 changes: 168 additions & 0 deletions
168
supabase/migrations/20260908142414_revoke_remaining_anon_oracle_rpc_execute.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,168 @@ | ||
| -- Complete the anon oracle RPC hardening started in | ||
| -- 20260824144021_revoke_anon_oracle_rpc_execute.sql. | ||
| -- | ||
| -- 1) Revoke anonymous EXECUTE on SECURITY DEFINER helpers that enumerate or | ||
| -- infer org/app/member state and are only needed from signed-in console JWT | ||
| -- traffic (authenticated role). Published CLI keeps anon EXECUTE on | ||
| -- get_user_id(text) and the capgkey-scoped helpers it still calls. | ||
| -- 2) Remove distinguishable "Organization does not exist" vs "NO_RIGHTS" | ||
| -- outcomes from org-member helpers that must remain anon-callable for CLI. | ||
| -- Internal/service_role callers still get ORG_NOT_FOUND for a missing org. | ||
|
|
||
| -- --------------------------------------------------------------------------- | ||
| -- Fix org-member helpers: same denial for missing org and missing permission. | ||
| -- --------------------------------------------------------------------------- | ||
|
|
||
| CREATE OR REPLACE FUNCTION public.check_org_members_2fa_enabled(org_id uuid) | ||
| RETURNS TABLE(user_id uuid, "2fa_enabled" boolean) | ||
| LANGUAGE plpgsql | ||
| SECURITY DEFINER | ||
| SET search_path = '' | ||
| AS $$ | ||
| BEGIN | ||
| -- Internal callers keep a distinguishable missing-org signal; non-internal | ||
| -- callers still collapse missing-org into NO_RIGHTS (anon oracle closed). | ||
| IF public.is_internal_request_role(public.current_request_role()) THEN | ||
| IF NOT EXISTS ( | ||
| SELECT 1 | ||
| FROM public.orgs | ||
| WHERE public.orgs.id = check_org_members_2fa_enabled.org_id | ||
| ) THEN | ||
| RAISE EXCEPTION 'ORG_NOT_FOUND'; | ||
| END IF; | ||
| ELSIF ( | ||
| NOT EXISTS ( | ||
| SELECT 1 | ||
| FROM public.orgs | ||
| WHERE public.orgs.id = check_org_members_2fa_enabled.org_id | ||
| ) | ||
| OR NOT public.rbac_check_permission_request( | ||
| public.rbac_perm_org_update_settings(), | ||
| check_org_members_2fa_enabled.org_id, | ||
| NULL::character varying, | ||
| NULL::bigint | ||
| ) | ||
| ) | ||
| THEN | ||
| RAISE EXCEPTION 'NO_RIGHTS'; | ||
| END IF; | ||
|
|
||
| RETURN QUERY | ||
| SELECT DISTINCT | ||
| rb.principal_id AS user_id, | ||
| COALESCE(public.has_2fa_enabled(rb.principal_id), false) AS "2fa_enabled" | ||
| FROM public.role_bindings rb | ||
| JOIN public.roles r ON r.id = rb.role_id | ||
| AND r.scope_type = rb.scope_type | ||
| WHERE rb.principal_type = public.rbac_principal_user() | ||
| AND rb.scope_type = public.rbac_scope_org() | ||
| AND rb.org_id = check_org_members_2fa_enabled.org_id | ||
| AND (rb.expires_at IS NULL OR rb.expires_at > now()) | ||
| AND r.name LIKE 'org_%'; | ||
| END; | ||
| $$; | ||
|
|
||
| ALTER FUNCTION public.check_org_members_2fa_enabled(uuid) OWNER TO postgres; | ||
|
|
||
| CREATE OR REPLACE FUNCTION public.check_org_members_password_policy(org_id uuid) | ||
| RETURNS TABLE( | ||
| user_id uuid, | ||
| email text, | ||
| first_name text, | ||
| last_name text, | ||
| password_policy_compliant boolean | ||
| ) | ||
| LANGUAGE plpgsql | ||
| SECURITY DEFINER | ||
| SET search_path = '' | ||
| AS $$ | ||
| BEGIN | ||
| -- Internal callers keep a distinguishable missing-org signal; non-internal | ||
| -- callers still collapse missing-org into NO_RIGHTS (anon oracle closed). | ||
| IF public.is_internal_request_role(public.current_request_role()) THEN | ||
| IF NOT EXISTS ( | ||
| SELECT 1 | ||
| FROM public.orgs | ||
| WHERE public.orgs.id = check_org_members_password_policy.org_id | ||
| ) THEN | ||
| RAISE EXCEPTION 'ORG_NOT_FOUND'; | ||
| END IF; | ||
| ELSIF ( | ||
| NOT EXISTS ( | ||
| SELECT 1 | ||
| FROM public.orgs | ||
| WHERE public.orgs.id = check_org_members_password_policy.org_id | ||
| ) | ||
| OR NOT public.rbac_check_permission_request( | ||
| public.rbac_perm_org_update_settings(), | ||
| check_org_members_password_policy.org_id, | ||
| NULL::character varying, | ||
| NULL::bigint | ||
| ) | ||
| ) | ||
| THEN | ||
| RAISE EXCEPTION 'NO_RIGHTS'; | ||
| END IF; | ||
|
|
||
| RETURN QUERY | ||
| SELECT DISTINCT | ||
| rb.principal_id AS user_id, | ||
| au.email::text, | ||
| u.first_name::text, | ||
| u.last_name::text, | ||
| public.user_meets_password_policy( | ||
| rb.principal_id, | ||
| check_org_members_password_policy.org_id | ||
| ) AS password_policy_compliant | ||
| FROM public.role_bindings rb | ||
| JOIN public.roles r ON r.id = rb.role_id | ||
| AND r.scope_type = rb.scope_type | ||
| JOIN auth.users au ON au.id = rb.principal_id | ||
| LEFT JOIN public.users u ON u.id = rb.principal_id | ||
| WHERE rb.principal_type = public.rbac_principal_user() | ||
| AND rb.scope_type = public.rbac_scope_org() | ||
| AND rb.org_id = check_org_members_password_policy.org_id | ||
| AND (rb.expires_at IS NULL OR rb.expires_at > now()) | ||
| AND r.name LIKE 'org_%'; | ||
| END; | ||
| $$; | ||
|
|
||
| ALTER FUNCTION public.check_org_members_password_policy(uuid) OWNER TO postgres; | ||
|
|
||
| -- --------------------------------------------------------------------------- | ||
| -- Revoke anonymous EXECUTE on org/member oracle RPCs (console uses JWT). | ||
| -- exist_app / exist_app_v2 stay anon-callable: they return false without a | ||
| -- valid capgkey and do not distinguish missing apps from denied access. | ||
| -- --------------------------------------------------------------------------- | ||
|
|
||
| REVOKE ALL ON FUNCTION public.get_org_members_rbac(uuid) FROM anon; | ||
|
|
||
| REVOKE ALL ON FUNCTION public.is_member_of_org(uuid, uuid) FROM anon; | ||
|
TorichanCapgo marked this conversation as resolved.
|
||
|
|
||
| REVOKE ALL ON FUNCTION public.update_org_invite_role_rbac( | ||
| uuid, uuid, text | ||
| ) FROM anon; | ||
|
|
||
| REVOKE ALL ON FUNCTION public.update_tmp_invite_role_rbac( | ||
| uuid, text, text | ||
| ) FROM anon; | ||
|
|
||
| GRANT EXECUTE ON FUNCTION public.get_org_members_rbac(uuid) TO authenticated; | ||
| GRANT EXECUTE ON FUNCTION public.get_org_members_rbac(uuid) TO service_role; | ||
|
|
||
| GRANT EXECUTE ON FUNCTION public.is_member_of_org(uuid, uuid) TO authenticated; | ||
| GRANT EXECUTE ON FUNCTION public.is_member_of_org(uuid, uuid) TO service_role; | ||
|
|
||
| GRANT EXECUTE ON FUNCTION public.update_org_invite_role_rbac( | ||
| uuid, uuid, text | ||
| ) TO authenticated; | ||
| GRANT EXECUTE ON FUNCTION public.update_org_invite_role_rbac( | ||
| uuid, uuid, text | ||
| ) TO service_role; | ||
|
|
||
| GRANT EXECUTE ON FUNCTION public.update_tmp_invite_role_rbac( | ||
| uuid, text, text | ||
| ) TO authenticated; | ||
| GRANT EXECUTE ON FUNCTION public.update_tmp_invite_role_rbac( | ||
| uuid, text, text | ||
| ) TO service_role; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.