Kurz gesagt
“RLS Disabled in Public” (Lint 0013_rls_disabled_in_public, Stufe ERROR) heißt: Eine Tabelle in einem exponierten Schema hat Row Level Security aus, während anon oder authenticated sie per select lesen kann. In meinem lokalen Test las der öffentliche Key aus so einer Tabelle alle 3 von 3 Zeilen und fügte mit 201 Created eine neue ein. Aktivieren Sie RLS, schreiben Sie eine Policy je Operation und prüfen Sie die Grants, alles in einer Migration.
Ich habe einen kostenlosen Supabase-Sicherheitscheck gebaut, und seine erste Regel, “RLS bei exponierten Tabellen deaktiviert”, ist derselbe Befund, den Supabases Security Advisor als Fehler meldet. Es ist die häufigste Lücke, die ich in Apps finde, die mit KI-Tools gebaut wurden, deshalb hier, was sie bedeutet und was sie erlaubte, als ich sie nachgestellt habe.
Was bedeutet “RLS disabled in public”?
Der Security Advisor führt einen Lint namens rls_disabled_in_public aus. Sein SQL meldet eine Tabelle, wenn drei Dinge gleichzeitig zutreffen:
- Es ist eine gewöhnliche Tabelle mit ausgeschalteter Row Level Security.
anonoderauthenticatedhatSELECTdarauf.- Ihr Schema steht in der Liste Exposed schemas der Data API, standardmäßig
public.
Die Lint-Seite stuft ihn als ERROR ein und nennt vollen Zugriff zum Anlegen, Lesen, Ändern und Löschen über das Internet “a critically unsafe configuration”. Das “public” im Namen ist das Schema, aber der Lint deckt jedes exponierte Schema ab, weshalb auch ein zusätzliches Schema auf dieser Liste einen Blick verdient; darüber habe ich in Supabase Exposed Schemas geschrieben.
Was kann der öffentliche Key mit so einer Tabelle tun?
Ich habe auf einem lokalen Supabase-Stack (CLI 2.109.1, Postgres 17.6, PostgREST 14.14) eine Tabelle orders mit drei erfundenen Kunden angelegt, mit den Grants, die bestehende Projekte neuen Tabellen geben, und RLS aus. Dann habe ich die Data API mit dem publishable key aufgerufen, wie es ein Browser tut:
| Anfrage mit dem publishable key | RLS aus | RLS an, keine Policy |
|---|---|---|
GET /rest/v1/orders?select=* |
200, alle 3 Zeilen mit Namen und E-Mail-Adressen |
200, [] |
POST /rest/v1/orders mit einer neuen Zeile |
201 Created |
401, 42501 “new row violates row-level security policy” |
Jeder, der Ihre App öffnet, kann den publishable key aus der Seite kopieren. Bei ausgeschalteter RLS ist der Key ein Lese- und Schreibzugang zu dieser Tabelle.
Wie beheben Sie das, ohne die App kaputt zu machen?
RLS allein zu aktivieren lässt die Tabelle für die App nichts mehr liefern, weil noch keine Policy existiert. Dieser leere Bildschirm ist der Moment, in dem Menschen, und KI-Tools, eine Policy mit using (true) hinzufügen, die jedem jede Zeile zurückgibt. Warum Updates und Deletes dann Erfolg melden, obwohl nichts geändert wird, steht in Supabase RLS aktivieren: was jede Anfrage danach liefert. Schreiben Sie die echten Policies in derselben Migration:
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);
Soll eine Tabelle öffentlich sein, etwa eine Liste veröffentlichter Artikel, lassen Sie RLS trotzdem an und schreiben Sie eine select-Policy für anon, ohne Schreib-Grants. Nutzen Sie die Data API nie und sprechen nur von Ihrem Server mit Postgres, entfernen Sie stattdessen public aus Exposed schemas, wie es Supabases Maintainer im selben Issue vorschlugen.
Damit neue Tabellen nie ohne RLS starten, hat Supabases Leitfaden zu Event Triggern einen Trigger, der RLS für jede in public angelegte Tabelle aktiviert. Und ab dem 30. Oktober 2026 bekommen neue Tabellen standardmäßig keine Data-API-Grants, antworten also mit 42501, bis Sie sie vergeben; das habe ich in Supabase 42501 permission denied behandelt.
Was beweist ein sauberes Ergebnis nicht?
Dass RLS an ist, sagt nichts darüber, ob die Policies stimmen. Im selben Test gab eine als using (true) geschriebene Policy dem öffentlichen Key wieder alle 3 Zeilen, und dieser Lint schweigt, sobald RLS an ist. Der Check hat dafür eine eigene Regel, “Policies, die jede Zeile erlauben”, und Supabase RLS testen zeigt, wie Sie jede Policy an echten Nutzern beweisen. Policies als Ausgangspunkt, je an echten Nutzern über die API ausgeführt, stehen in Supabase RLS Policy Beispiele, je per API getestet.