Which of your Supabase tables can anyone read?

Connect your project read-only and GuardLayer checks RLS, policies, grants and functions as they are right now. No account needed: access lasts at most an hour in your browser, and nothing from your project is stored.

Check a project directly

Read-only access. GuardLayer reads table settings, policies, grants and bucket flags through Supabase's read-only query endpoint. It never reads rows and can't change anything.

Prefer not to connect? Run one read-only query in your SQL editor and paste the result instead.

1. Run this in your Supabase SQL editor

It only reads the catalog: table names, RLS flags, policies, grants and bucket settings. No rows, and this way GuardLayer never connects to your database or sees a key.

-- GuardLayer live check: read-only, returns one JSON value. No table data.
select json_build_object(
  'version', 1,
  'tables', (
    select coalesce(json_agg(json_build_object(
      'name', c.relname,
      'kind', c.relkind,
      'rls', c.relrowsecurity,
      'invoker', coalesce(c.reloptions::text[] && array['security_invoker=true','security_invoker=on','security_invoker=1'], false),
      'anon_read', has_table_privilege('anon', c.oid, 'select'),
      'anon_write', has_table_privilege('anon', c.oid, 'insert,update,delete'),
      'auth_read', has_table_privilege('authenticated', c.oid, 'select'),
      'est_rows', c.reltuples::bigint
    ) order by c.relname), '[]'::json)
    from pg_class c join pg_namespace n on n.oid = c.relnamespace
    where n.nspname = 'public' and c.relkind in ('r', 'p', 'v', 'm')
  ),
  'policies', (
    select coalesce(json_agg(json_build_object(
      'schema', schemaname, 'table', tablename, 'name', policyname,
      'cmd', cmd, 'roles', roles, 'permissive', permissive,
      'using', qual, 'check', with_check
    ) order by schemaname, tablename, policyname), '[]'::json)
    from pg_policies where schemaname in ('public', 'storage')
  ),
  'functions', (
    select coalesce(json_agg(json_build_object(
      'name', p.proname,
      'args', pg_get_function_identity_arguments(p.oid),
      'anon', has_function_privilege('anon', p.oid, 'execute'),
      'trigger', p.prorettype in ('pg_catalog.trigger'::pg_catalog.regtype, 'pg_catalog.event_trigger'::pg_catalog.regtype)
    ) order by p.proname), '[]'::json)
    from pg_proc p join pg_namespace n on n.oid = p.pronamespace
    where n.nspname = 'public' and p.prosecdef
  ),
  'buckets', (
    select coalesce(json_agg(json_build_object('id', id, 'public', public) order by id), '[]'::json)
    from storage.buckets
  )
) as guardlayer_snapshot;

2. Paste the result

Copy the single value in the guardlayer_snapshot column.

The snapshot is checked and discarded, never stored.