---
title: "Supabase „RLS disabled in public“: co to znamená"
description: "Co znamená chyba Advisoru rls_disabled_in_public v Supabase, co udělal veřejný klíč s takovou tabulkou v mém lokálním testu a jak to bezpečně opravit."
url: "https://madsalt.tech/cs/notes/supabase-rls-disabled-in-public/"
author: "Denys Zaichenko"
author_url: "https://madsalt.tech/cs/about/"
language: "cs"
published: 2026-10-28
---

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

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](https://madsalt.tech/cs/tools/supabase-security-check/) 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](https://github.com/supabase/splinter/issues/82) 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](https://supabase.github.io/splinter/0013_rls_disabled_in_public/) 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](https://madsalt.tech/cs/notes/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ů.](https://madsalt.tech/charts/cs/supabase-rls-disabled-in-public.svg)

*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](https://madsalt.tech/cs/blog/how-to-enable-rls-in-supabase/). Skutečné politiky napište ve stejné migraci:

```sql
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](https://github.com/supabase/splinter/issues/82) navrhli správci Supabase.

Aby nové tabulky nikdy nezačínaly bez RLS, má [průvodce event triggery](https://supabase.com/docs/guides/database/postgres/event-triggers) 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](https://madsalt.tech/cs/notes/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](https://madsalt.tech/cs/blog/how-to-test-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](https://madsalt.tech/cs/blog/supabase-rls-policy-examples/).
