Skip to content

Lock down internal tables and quota view#381

Merged
simonsmallchua merged 6 commits into
mainfrom
work/gracious-yonath-dda22f
May 9, 2026
Merged

Lock down internal tables and quota view#381
simonsmallchua merged 6 commits into
mainfrom
work/gracious-yonath-dda22f

Conversation

@simonsmallchua
Copy link
Copy Markdown
Contributor

@simonsmallchua simonsmallchua commented May 9, 2026

Summary

Migration A of three, addressing Supabase database linter findings verified against actual usage in this repo.

  • Enables RLS on task_outbox, task_outbox_dead, lighthouse_runs (no policies → deny-all for non-service-role).
  • Revokes anon/authenticated table grants on the same three tables.
  • Sets security_invoker = true on the organisation_quota_status view so it honours the caller's RLS rather than the creator's.

Why this is safe

  • All three tables and the view are only accessed by the Go server using the
    service role key, which bypasses both grants and RLS. Verified by grepping
    internal/, cmd/, and web/ for any usage — no frontend .rpc() or
    .from() calls reference these objects.
  • No policies are added, so behaviour for the existing service-role caller is
    unchanged.

Test plan

  • Supabase migration GitHub Action passes.
  • task_outbox sweeper still drains queued tasks on a review app.
  • Lighthouse scheduler still inserts/updates lighthouse_runs rows.
  • organisation_quota_status view returns expected rows for a logged-in
    org user.

View in Codesmith
Need help on this PR? Tag @codesmith with what you need.

  • Let Codesmith autofix CI failures and bot reviews

Summary by CodeRabbit

  • Security

    • Tightened access to internal server tables, enabled RLS on them, and revoked public privileges on multiple internal helper routines and RPCs.
    • Switched quota/status view to evaluate permissions as the caller, enforcing per-user RLS context.
  • Performance

    • Optimised RLS policies for lower per-query overhead, scoped service-role policies, and pinned function execution contexts.
    • Added covering indexes for previously unindexed foreign-key paths.
  • Documentation

    • Added guidance documenting advisory findings and rationale for deferred items.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 9, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f1ea1207-648e-42b6-8d7c-ea19e22dc3fd

📥 Commits

Reviewing files that changed from the base of the PR and between 66ba2f6 and 09e4bab.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • docs/security/SUPABASE_ADVISORS.md
  • supabase/migrations/20260509111837_add_covering_indexes_for_unindexed_fks.sql
✅ Files skipped from review due to trivial changes (2)
  • CHANGELOG.md
  • docs/security/SUPABASE_ADVISORS.md

📝 Walkthrough

Walkthrough

Three Supabase migrations tighten DB privileges and RLS: lock down internal tables and set the quota view to security_invoker; revoke anon/authenticated EXECUTE on many SECURITY DEFINER helpers; and rewrite RLS policies to use (SELECT auth.uid()) plus pin two functions' search_path. CHANGELOG and advisor docs updated; nine covering FK indexes added.

Changes

Security Hardening Migration

Layer / File(s) Summary
Migration scope and comments
supabase/migrations/20260509101603_lock_down_internal_tables_and_quota_view.sql
Migration header documents intent to lock down internal tables (task_outbox, task_outbox_dead, lighthouse_runs) and update the organisation_quota_status view.
Internal table privileges
supabase/migrations/20260509101603_lock_down_internal_tables_and_quota_view.sql
Revokes anon and authenticated privileges on the three internal tables.
Enable RLS on internal tables
supabase/migrations/20260509101603_lock_down_internal_tables_and_quota_view.sql
Enables row-level security on the three internal tables without adding policies.
Quota view security mode
supabase/migrations/20260509101603_lock_down_internal_tables_and_quota_view.sql
Sets security_invoker=true on organisation_quota_status so the view enforces the caller's RLS context during execution.
Changelog: RLS & view note
CHANGELOG.md
Adds an Unreleased -> Security note documenting enabled RLS and the view security change.
Changelog: RPC EXEC revocations note
CHANGELOG.md
Extends Security note listing EXECUTE revocations on multiple SECURITY DEFINER helper functions and which RLS helpers remain callable.
Changelog: Performance note
CHANGELOG.md
Documents RLS policy rewrites and pinned search_path for functions.

RPC EXEC Revocations Migration

Layer / File(s) Summary
RPC migration header
supabase/migrations/20260509102622_revoke_anon_execute_on_internal_rpcs.sql
Migration header describing revocation of EXECUTE on SECURITY DEFINER public helper functions from anon/authenticated.
Revoke EXECUTE: GA token funcs
supabase/migrations/20260509102622_revoke_anon_execute_on_internal_rpcs.sql
Revokes EXECUTE on store_ga_token, get_ga_token, delete_ga_token.
Revoke EXECUTE: GA account token funcs
supabase/migrations/20260509102622_revoke_anon_execute_on_internal_rpcs.sql
Revokes EXECUTE on store_ga_account_token, get_ga_account_token, delete_ga_account_token.
Revoke EXECUTE: Slack token funcs
supabase/migrations/20260509102622_revoke_anon_execute_on_internal_rpcs.sql
Revokes EXECUTE on store_slack_token, get_slack_token, delete_slack_token.
Revoke EXECUTE: Webflow token funcs
supabase/migrations/20260509102622_revoke_anon_execute_on_internal_rpcs.sql
Revokes EXECUTE on store_webflow_token, get_webflow_token, delete_webflow_token.
Revoke EXECUTE: vault cleanup funcs
supabase/migrations/20260509102622_revoke_anon_execute_on_internal_rpcs.sql
Revokes EXECUTE on cleanup_ga_vault_secret, cleanup_slack_vault_secret, cleanup_webflow_vault_secret.
Revoke EXECUTE: Slack user-link helpers
supabase/migrations/20260509102622_revoke_anon_execute_on_internal_rpcs.sql
Revokes EXECUTE on auto_link_slack_user, auto_link_existing_slack_users, sync_slack_user_id.
Revoke EXECUTE: increment_daily_usage
supabase/migrations/20260509102622_revoke_anon_execute_on_internal_rpcs.sql
Revokes EXECUTE on increment_daily_usage(uuid, integer).

RLS Optimisation & Function hardening Migration

Layer / File(s) Summary
Optimise migration header
supabase/migrations/20260509104940_optimise_rls_and_function_search_path.sql
Migration header describing RLS policy rewrites and function search_path pinning.
Rewrite notifications policy
supabase/migrations/20260509104940_optimise_rls_and_function_search_path.sql
Drops and recreates public.notifications SELECT policy to use (SELECT auth.uid()).
Rewrite daily_usage policies
supabase/migrations/20260509104940_optimise_rls_and_function_search_path.sql
Rewrites public.daily_usage policies and scopes the service-role policy to TO service_role.
Rewrite GA connections policies
supabase/migrations/20260509104940_optimise_rls_and_function_search_path.sql
Rewrites all RLS policies on public.google_analytics_connections to use (SELECT auth.uid()).
Rewrite GA accounts policies
supabase/migrations/20260509104940_optimise_rls_and_function_search_path.sql
Rewrites all RLS policies on public.google_analytics_accounts to use (SELECT auth.uid()).
Rewrite organisation_domains policies
supabase/migrations/20260509104940_optimise_rls_and_function_search_path.sql
Rewrites RLS policies on public.organisation_domains to use (SELECT auth.uid()).
Pin function search_path
supabase/migrations/20260509104940_optimise_rls_and_function_search_path.sql
Pins search_path for update_job_queue_counters() and get_daily_quota_remaining(uuid) to pg_catalog, public.

Docs & Indexes

Layer / File(s) Summary
Advisor docs intro
docs/security/SUPABASE_ADVISORS.md
Adds document introduction describing purpose and usage for Supabase Studio Advisors findings.
Advisor docs: keeps / deferred / resolved
docs/security/SUPABASE_ADVISORS.md
Adds “Deliberate keeps”, “Deferred”, and “Resolved in this PR” sections mapping lints and migrations.
Indexes migration
supabase/migrations/20260509111837_add_covering_indexes_for_unindexed_fks.sql
Adds nine CREATE INDEX IF NOT EXISTS covering indexes for FK columns flagged unindexed.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant View as organisation_quota_status
  participant RLS
  Caller->>View: SELECT * FROM organisation_quota_status
  View->>RLS: evaluate using caller's role/context
  RLS->>Caller: return rows filtered by caller's RLS
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 A lock clicks shut on tables deep,
No prying eyes shall secrets keep,
Service role guards the midnight chore,
Views now heed the caller more—
The burrow rests, secure and neat.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly and accurately summarizes the main objective of the changeset: locking down internal tables and the quota view with RLS and privilege revocation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 work/gracious-yonath-dda22f

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

@supabase
Copy link
Copy Markdown

supabase Bot commented May 9, 2026

Updates to Preview Branch (work/gracious-yonath-dda22f) ↗︎

Deployments Status Updated
Database Sat, 09 May 2026 11:42:38 UTC
Services Sat, 09 May 2026 11:42:38 UTC
APIs Sat, 09 May 2026 11:42:38 UTC

Tasks are run on every commit but only new migration files are pushed.
Close and reopen this PR if you want to apply changes from existing seed or migration files.

Tasks Status Updated
Configurations Sat, 09 May 2026 11:42:39 UTC
Migrations Sat, 09 May 2026 11:42:42 UTC
Seeding Sat, 09 May 2026 11:42:44 UTC
Edge Functions Sat, 09 May 2026 11:42:44 UTC

View logs for this Workflow Run ↗︎.
Learn more about Supabase for Git ↗︎.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

Release Versions

App patch: v0.34.7v0.34.8

Changelog

Security

  • Enabled RLS (no policies) and revoked anon/authenticated grants on
    task_outbox, task_outbox_dead, and lighthouse_runs; these tables are
    only accessed by the Go server via the service role.
  • Switched the organisation_quota_status view to security_invoker = true so
    it honours the caller's RLS rather than the creator's.
  • Revoked anon/authenticated EXECUTE on 19 server-internal
    SECURITY DEFINER functions (OAuth token store/get/delete for Google
    Analytics, Slack, and Webflow; vault cleanup helpers; Slack user-link helpers;
    increment_daily_usage). These RPCs are only called by the Go server via the
    service role; the three RLS-helper functions used inside policies
    (user_is_member_of, user_organisation_id, user_organisations) remain
    callable.

Performance

  • Rewrote 14 RLS policies on notifications, daily_usage,
    google_analytics_connections, google_analytics_accounts, and
    organisation_domains to wrap auth.uid() in a (select …) so it is
    evaluated once per query instead of once per row.
  • Scoped the Service role can manage usage policy on daily_usage
    TO service_role so it no longer fires during anon/authenticated SELECTs,
    removing the multiple-permissive-policies overhead.
  • Pinned search_path on update_job_queue_counters and
    get_daily_quota_remaining.
  • Added covering indexes on nine previously-unindexed foreign keys
    (google_analytics_accounts.installing_user_id,
    google_analytics_connections.installing_user_id,
    lighthouse_runs.source_task_id, organisation_invites.created_by,
    page_analytics.ga_connection_id, platform_org_mappings.created_by,
    slack_connections.installing_user_id, task_outbox_dead.lighthouse_run_id,
    webflow_connections.installing_user_id) so cascade deletes and FK joins no
    longer fall back to sequential scans.

Documentation

  • Added
    docs/security/SUPABASE_ADVISORS.md
    recording the deliberate "won't fix" advisor findings (the three RLS-helper
    SECURITY DEFINER functions, the empty-policy state of domain_hosts) and
    deferred items (unused indexes, Auth DB connection strategy).

@codecov
Copy link
Copy Markdown

codecov Bot commented May 9, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

🐝 Review App Deployed

Homepage: https://hover-pr-381.fly.dev
Dashboard: https://hover-pr-381.fly.dev/dashboard

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

🐝 Review App Deployed

Homepage: https://hover-pr-381.fly.dev
Dashboard: https://hover-pr-381.fly.dev/dashboard

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

🐝 Review App Deployed

Homepage: https://hover-pr-381.fly.dev
Dashboard: https://hover-pr-381.fly.dev/dashboard

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

🐝 Review App Deployed

Homepage: https://hover-pr-381.fly.dev
Dashboard: https://hover-pr-381.fly.dev/dashboard

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

🐝 Review App Deployed

Homepage: https://hover-pr-381.fly.dev
Dashboard: https://hover-pr-381.fly.dev/dashboard

@simonsmallchua simonsmallchua merged commit 7b4b52a into main May 9, 2026
21 checks passed
@simonsmallchua simonsmallchua deleted the work/gracious-yonath-dda22f branch May 9, 2026 12:26
simonsmallchua added a commit that referenced this pull request May 9, 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