přeskočit na obsah
[JJ]
zpět na snippety
sqlsupabasepostgressecurityaudit2. 5. 2026

Supabase RLS audit query

Jeden SQL co ti řekne které tabulky mají RLS, kolik policies a které veřejné views obcházejí ochranu. Pouštím to 1× za 6 měsíců na všech projektech.

Pravidelný RLS audit je jediný způsob, jak nepřehlédnout, že někdo vytvořil tabulku bez ochrany. Tenhle skript ti vypíše seznam všech veřejně přístupných tabulek a kolik mají policies.

Hlavní audit

sql
-- RLS coverage audit pro Supabase (self-hosted i hosted)
SELECT
  c.relname                              AS table_name,
  c.relrowsecurity                       AS rls_enabled,
  c.relforcerowsecurity                  AS rls_forced,
  COUNT(p.polname)                       AS policy_count,
  STRING_AGG(p.polname, ', ' ORDER BY p.polname) AS policies
FROM pg_class c
  JOIN pg_namespace n ON n.oid = c.relnamespace
  LEFT JOIN pg_policy p ON p.polrelid = c.oid
WHERE c.relkind = 'r'
  AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'supabase_migrations')
GROUP BY c.relname, c.relrowsecurity, c.relforcerowsecurity
ORDER BY c.relrowsecurity ASC, c.relname;

Veřejné views co obchází RLS

Views s SECURITY DEFINER přečte data napřímo — pozor.

sql
SELECT
  schemaname,
  viewname,
  viewowner,
  definition
FROM pg_views
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
  AND definition ILIKE '%security definer%';

Funkce bez search_path (security hole)

sql
SELECT
  n.nspname  AS schema,
  p.proname  AS function,
  pg_get_function_identity_arguments(p.oid) AS args,
  p.prosecdef AS is_definer,
  COALESCE(
    (SELECT setting FROM unnest(p.proconfig) AS setting WHERE setting LIKE 'search_path=%' LIMIT 1),
    'NOT SET'
  ) AS search_path
FROM pg_proc p
  JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE p.prosecdef = true
  AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'pg_temp');

Pokud search_path u DEFINER funkce není explicitně nastaven, útočník může přepsat vyhledávací cestu a podvést funkci.