Přejít na obsah

Supabase „RLS disabled in public“: co to znamená

Supabase

Zobrazit jako MarkdownOtevřít v ClaudeOtevřít v ChatGPTOtevřít v Perplexity

Otázka se zkopíruje také. Pokud se chat otevře prázdný, vložte ji.

TL;DR

„RLS Disabled in Public“ (lint 0013_rls_disabled_in_public, úroveň ERROR) znamená, že tabulka ve zpřístupněném schématu má vypnutou row level security, zatímco anon nebo authenticated z ní může dělat select. V mém lokálním testu veřejný klíč z takové tabulky přečetl 3 ze 3 řádků a vložil nový s 201 Created. Zapněte RLS, přidejte politiku pro každou operaci a zkontrolujte granty, vše v jedné migraci.

Postavil jsem bezplatný bezpečnostní checker pro Supabase a jeho první pravidlo, „RLS vypnuté u zpřístupněných tabulek“, je stejný nález, který Security Advisor Supabase hlásí jako chybu. Je to nejčastější díra, kterou nacházím v aplikacích postavených s AI nástroji, takže tady je, co znamená a co umožnila, když jsem ji reprodukoval.

Co znamená „RLS disabled in public“?

Security Advisor spouští lint rls_disabled_in_public. Jeho SQL označí tabulku, když platí tři věci zároveň:

  1. Je to obyčejná tabulka s vypnutou row level security.
  2. anon nebo authenticated na ní má SELECT.
  3. Její schéma je v seznamu Exposed schemas Data API, což je ve výchozím stavu public.

Stránka lintu ho hodnotí jako ERROR a plný create, read, update a delete přes internet nazývá „kriticky nebezpečnou konfigurací“. „Public“ v názvu je schéma, ale lint pokrývá každé zpřístupněné schéma, a proto stojí za pohled i extra schéma na tomto seznamu; psal jsem o tom v poznámce Supabase exposed schemas.

Co může veřejný klíč udělat s takovou tabulkou?

Vytvořil jsem tabulku orders se třemi fiktivními zákazníky na lokálním Supabase (CLI 2.109.1, Postgres 17.6, PostgREST 14.14), s granty, které existující projekty dávají novým tabulkám, a s vypnutým RLS. Pak jsem volal Data API s publishable key, jako to dělá prohlížeč:

Jedna tabulka, veřejný klíč, RLS vypnuté a zapnuté. Lokální Supabase, 3 řádky fiktivních objednávek. RLS vypnuté, čtení: Publishable key → orders, RLS vypnuté → 3 z 3 řádků; RLS vypnuté, vložení: Publishable key → orders, RLS vypnuté → 201 Created; RLS zapnuté, zatím bez politiky: Publishable key → orders, RLS zapnuté → 0 řádků.
Moje reprodukce na lokálním Supabase, 23. října 2026.
Požadavek s publishable key RLS vypnuté RLS zapnuté, bez politiky
GET /rest/v1/orders?select=* 200, všechny 3 řádky se jmény a e-maily 200, []
POST /rest/v1/orders s novým řádkem 201 Created 401, 42501 „new row violates row-level security policy“

Kdokoli, kdo otevře vaši aplikaci, si může zkopírovat publishable key ze stránky. S vypnutým RLS je klíč propustkou ke čtení i zápisu do té tabulky.

Jak to opravit, aniž rozbijete aplikaci?

Samotné zapnutí RLS způsobí, že tabulka aplikaci nevrátí nic, protože ještě není žádná politika. Právě tehdy lidé, a AI nástroje, přidají politiku s using (true), která vrátí každý řádek všem. Proč update a delete pak hlásí úspěch, ale nic nezmění, je v článku How to enable RLS in Supabase: co vrátí po každém kroku. Skutečné politiky napište ve stejné migraci:

alter table public.orders enable row level security;

revoke all on table public.orders from anon, authenticated;
grant select, insert on table public.orders to authenticated;

create policy "Customers read their orders"
on public.orders for select
to authenticated
using ((select auth.uid()) = user_id);

create policy "Customers create their orders"
on public.orders for insert
to authenticated
with check ((select auth.uid()) = user_id);

Pokud má být tabulka veřejná, například seznam publikovaných článků, nechte RLS i tak zapnuté a napište jednu politiku select pro anon, bez zápisových grantů. Pokud Data API nepoužíváte a s Postgresem mluvíte jen ze serveru, odstraňte raději public z Exposed schemas, jak ve stejném issue navrhli správci Supabase.

Aby nové tabulky nikdy nezačínaly bez RLS, má průvodce event triggery od Supabase trigger, který RLS zapne na každé tabulce vytvořené v public. A od 30. října 2026 nové tabulky nedostávají ve výchozím stavu žádné granty Data API, takže odpovídají 42501, dokud jim grant nedáte; psal jsem o tom v poznámce Supabase 42501 permission denied.

Co čistý výsledek nedokazuje?

To, že je RLS zapnuté, neříká nic o tom, zda jsou politiky správné. Ve stejném testu politika napsaná jako using (true) dala veřejnému klíči opět všechny 3 řádky a tento lint mlčí, jakmile je RLS zapnuté. Checker má pro to samostatné pravidlo, „Politiky, které povolují každý řádek“, a jak testovat Supabase RLS ukazuje, jak každou politiku dokázat proti skutečným uživatelům. Politiky, od kterých můžete začít, každou vyzkoušenou proti skutečným uživatelům přes API, jsou v článku Supabase RLS policy: příklady otestované přes API.

© 2026 Denys Zaichenko. Původní článek: https://madsalt.tech/cs/notes/supabase-rls-disabled-in-public/