Wer heute mit Supabase und KI-gestützter Entwicklung arbeitet, kann in sehr kurzer Zeit ein produktives Backend, Authentifizierung und APIs aufsetzen. RLS ist die letzte harte Sicherheitsgrenze.
Kurzantwort
Wer heute mit Supabase und KI-gestützter Entwicklung arbeitet, kann in sehr kurzer Zeit ein produktives Backend, Authentifizierung und APIs aufsetzen. Genau deshalb ist Row-Level Security oft die letzte wirklich harte Sicherheitsgrenze zwischen „schnell veröffentlicht“ und „versehentlich Daten offengelegt“. Das Thema ist aktuell: Laut der Stack Overflow Developer Survey 2025 nutzen oder planen 84 % der Befragten KI-Tools im Entwicklungsprozess, und 51 % der Professional Developers verwenden sie täglich.[12] Gleichzeitig misstrauen mehr Entwicklerinnen und Entwickler der Genauigkeit von KI-Ausgaben, als ihr zu vertrauen.[3] GitHub berichtet ebenfalls, dass nahezu alle Befragten in seiner Studie bereits KI-Coding-Tools genutzt haben.[13] Für „vibe-coded“ Apps heißt das: Tempo ist normal geworden, menschliche Sicherheitsprüfung bleibt unverzichtbar.
Schnellantwort: Row-Level Security (RLS) ist in Supabase kein „nice to have“, sondern die zentrale Autorisierungsschicht für alles, was Sie direkt aus Browser, Mobile App oder Data API gegen Postgres zugänglich machen. Die häufigsten Fehler sind nicht aktivierte RLS auf exponierten Tabellen, zu breite oder mehrfach permissive Policies, unsichere Rollenlogik über user_metadata, Views oder materialized views, die RLS umgehen, falsch eingesetzte service_role- oder Secret-Keys sowie unzureichende Tests.[4][5][7][8][10][11] Sichere RLS bedeutet deshalb: Least Privilege, deny by default, saubere Trennung zwischen Endnutzer- und Admin-Zugriff, explizite Policy-Tests und regelmäßige Audits Ihrer Datenzugriffsregeln.
Für Gründerteams ist die wichtigste praktische Erkenntnis: RLS ist mächtig, aber unforgiving. Wenn Ihre App Mandanten trennt, personenbezogene Daten verarbeitet oder Admin-Funktionen über RPC und serverseitige Jobs ausführt, sollten Sie RLS nicht als KI-generiertes Nebenprodukt behandeln, sondern als bewusst designten Teil Ihrer Sicherheitsarchitektur. Das ist nicht nur technisch vernünftig; Datenschutzregime wie die DSGVO verlangen „geeignete technische und organisatorische Maßnahmen“ sowie regelmäßige Prüfung ihrer Wirksamkeit.[8][9] RLS kann dazu beitragen, ersetzt aber weder ein vollständiges Sicherheitskonzept noch rechtliche Prüfung.
Row-Level Security verstehen
Row-Level Security, kurz RLS, ist eine PostgreSQL-Funktion, mit der sich pro Zeile steuern lässt, welche Datensätze ein bestimmter Benutzer lesen, einfügen, ändern oder löschen darf. PostgreSQL beschreibt RLS als Ergänzung zum normalen Rechtesystem über GRANT: Während GRANT den Tabellenzugriff regelt, bestimmen Policies bei aktivierter RLS, welche einzelnen Zeilen sichtbar oder veränderbar sind.[7] In Supabase ist das besonders wichtig, weil Supabase die Datenbank so ausrichtet, dass sie direkt vom Client abgefragt werden kann; die eigene Dokumentation beschreibt RLS deshalb ausdrücklich als den Mechanismus, der Datenbankzugriffe aus dem Client absichert.[4]
In Supabase werden Requests typischerweise auf die Postgres-Rollen anon, authenticated oder service_role abgebildet. anon steht für nicht eingeloggte Requests, authenticated für eingeloggte Nutzer, und service_role ist die privilegierte Rolle für erhöhten Zugriff.[6] Gerade diese Rollenabbildung ist entscheidend: Wer mit publishable oder anon-Key aus dem Frontend arbeitet, verlässt sich auf RLS. Wer dagegen service_role oder neue Secret Keys verwendet, arbeitet bewusst mit Rollen, die RLS umgehen können.
Ein wichtiger technischer Punkt wird oft missverstanden: RLS schützt nur dann, wenn sie tatsächlich aktiviert ist. PostgreSQL selbst sagt klar, dass Tabellen standardmäßig keine Policies haben und normale Tabellenrechte dann unverändert gelten.[7] Erst wenn Sie ALTER TABLE ... ENABLE ROW LEVEL SECURITY aktivieren, wird der Tabellenzugriff durch Policies eingeschränkt; existiert dann keine passende Policy, gilt default deny. Supabase ergänzt: Jede exponierte Tabelle ohne aktivierte RLS kann über passende Data-API-Grants erreichbar sein.[4][5] Anders gesagt: „Keine Policy“ ist nicht automatisch sicher; sicher ist „RLS aktiv + sauber definierte Policy“.
Ebenso wichtig ist zu verstehen, was RLS nicht leistet. Supabase weist darauf hin, dass RLS allein nicht immer genügt, etwa für Rate Limits, Quoten, zusätzliche API-Key-Prüfungen oder das generelle Unterbinden direkter Tabellen- und Funktionszugriffe in exponierten Schemas.[5] OWASP empfiehlt ergänzend Least Privilege, deny by default, konsistente Autorisierung auf jeder Anfrage und Tests der Autorisierungslogik.[8] RLS ist also der Kern Ihrer Datenautorisierung, aber nicht Ihr gesamtes Sicherheitsmodell.
Häufige RLS-Konfigurationsfehler
Der häufigste Fehler ist banal: RLS wurde auf einer exponierten Tabelle nie aktiviert. Supabase sagt ausdrücklich, dass RLS auf Tabellen in exponierten Schemas – standardmäßig public – immer aktiv sein sollte.[5] Tabellen, die über das Dashboard erstellt werden, erhalten RLS standardmäßig; Tabellen aus SQL Editor oder Raw SQL nicht unbedingt.[4] Wer im Sprint schnell eine neue Tabelle anlegt und „Policies später“ nachholt, baut oft unwissentlich eine öffentliche Lesefläche.
Der zweite Klassiker sind zu breite Policies. PostgreSQL kombiniert mehrere anwendbare permissive Policies standardmäßig mit OR; restrictive Policies werden mit AND kombiniert.[7] Das bedeutet in der Praxis: Zwei scheinbar harmlose „erlaubende“ Policies können zusammen viel mehr freigeben als beabsichtigt. Supabase’ Security Advisor warnt deshalb ausdrücklich vor „multiple permissive policies“ und vor Policies mit Always-True-Bedingungen wie USING (true), weil sie den Sinn von RLS faktisch aushebeln.[11]
Ein dritter Fehler ist Rollen oder Mandantschaft aus benutzerveränderbaren Metadaten abzuleiten. Supabase dokumentiert klar, dass raw_user_meta_data von authentifizierten Nutzern über supabase.auth.update() geändert werden kann und deshalb kein guter Ort für Autorisierungsdaten ist.[4] Dagegen ist raw_app_meta_data der richtige Ort für nicht durch Endnutzer änderbare Claims wie Rollen oder Pricing-Pläne. Zusätzlich weist Supabase darauf hin, dass JWT-basierte Informationen nicht immer „frisch“ sind: Wird ein Nutzer aus einem Team entfernt, spiegelt sich das in auth.jwt() erst nach Token-Refresh. Für hochkritische Berechtigungen sollten Sie diesen Verzögerungseffekt bewusst berücksichtigen.
Ein weiterer häufiger Fehler ist die Annahme, Views würden RLS automatisch respektieren. In Supabase ist das ausdrücklich falsch: Views umgehen RLS standardmäßig, weil sie meist mit dem postgres-Benutzer erstellt werden und als security definer laufen.[14] Erst ab Postgres 15 können Sie ein View mit security_invoker = true so konfigurieren, dass beim Aufruf durch anon oder authenticated die RLS der zugrunde liegenden Tabellen beachtet wird. Ältere Vorgehensweisen sind: Zugriff auf das View entziehen oder es in ein nicht exponiertes Schema verschieben. Materialized views sind noch heikler: Supabase’ Advisor warnt, dass materialized views nicht mit RLS geschützt werden können; wenn sie in der API exponiert werden, ist der enthaltene Datenstand für berechtigte API-Rollen sichtbar.[15]
Ebenso gefährlich ist die falsche Verwendung von SECURITY DEFINER-Funktionen. Supabase erklärt, dass RLS für Funktionen nicht direkt gilt; der Zugriff muss über EXECUTE-Rechte gesteuert werden, und SECURITY DEFINER-Funktionen verdienen besondere Prüfung.[5] Solche Funktionen sollten nie in einem exponierten Schema liegen. Sie sind nützlich, um bestimmte Autorisierungsabfragen effizient oder ohne rekursive Policy-Probleme zu Kapseln, können aber ebenso leicht zu Privilegieneskalation oder ungewollt direkt aufrufbaren Admin-Helfern werden.
Schließlich scheitern viele Teams an falschen Testannahmen rund um privilegierte Rollen. PostgreSQL sagt eindeutig, dass Superuser, Rollen mit BYPASSRLS und normalerweise auch Tabellenbesitzer RLS umgehen.[7] Wer Policies im SQL Editor, als Tabellen-Owner oder mit einem privilegierten Backend-User testet, kann dadurch ein trügerisch positives Ergebnis bekommen. Umgekehrt sind service_role und Secret Keys in Supabase bewusst zum Umgehen von RLS gedacht und dürfen nie ins Frontend gelangen.[6]
Ein vereinfachtes Beispiel macht den Unterschied sichtbar:
-- Unsicher: gibt allen eingeloggten Nutzern alle Profile
create policy "Profiles readable"
on public.profiles
for select
to authenticated
using (true);
-- Sicherer: nur eigenes Profil
create policy "Users read own profile"
on public.profiles
for select
to authenticated
using ((select auth.uid()) = id);Das Muster dahinter entspricht den Supabase-Empfehlungen: möglichst explizit an auth.uid() oder an nicht benutzerveränderbare App-Claims koppeln, statt breit mit true oder mit unsicheren Metadaten zu arbeiten.[6] Supabase empfiehlt sogar, bei auth.uid() die Authentifizierung explizit mitzuprüfen, weil auth.uid() ohne gültige Session null liefert.
Praxisnahe Beispiele realer RLS-Fehlschläge
Ein sehr reales Fehlmuster ist die versehentliche Datenfreigabe über ein View. Supabase’ Security Advisor bezeichnet das nicht als theoretisches Problem, sondern als konkrete Fehlkonfiguration: „View bypasses row-level security“.[14] Die Dokumentation erläutert, dass ein View im public-Schema mit erhöhten Privilegien laufen und dadurch RLS ignorieren kann. Das ist genau der Typ Fehler, der in schnell iterierten Projekten entsteht: Die Tabelle selbst ist sauber abgesichert, ein bequemes View für das Frontend aber nicht.
Ein zweites veröffentlichtes Fehlmuster ist die Exponierung einer materialized view in der API. Supabase warnt hier ausdrücklich, dass materialized views nicht per RLS geschützt werden können und ihr Inhalt dadurch für berechtigte API-Rollen sichtbar wird.[15] In der Praxis passiert das häufig, wenn Teams Performance optimieren oder Reporting-Funktionen „einfach kurz“ als materialized view bereitstellen. Sicherheitstechnisch ist das heikel, weil sich dadurch Daten aus mehreren geschützten Tabellen in einer ungeschützten Cache-Struktur sammeln können.
Ein drittes Beispiel kommt direkt aus einer Supabase-Community-Diskussion von Mai 2025: Ein Nutzer, der nach eigener Aussage mit KI und ohne Programmiererfahrung eine App baut, stieß auf ein RLS UPDATE Violation-Problem, obwohl die UPDATE-Policy permissiv formuliert war.[16] In der Antwort wies ein Supabase-Kollaborator darauf hin, dass bei Updates auch SELECT-bezogene Policy-Bedingungen und die Sichtbarkeit alter bzw. neuer Zeilen relevant sein können.[7] Das Beispiel zeigt zwei typische Risiken von vibe-coded Apps: Erstens wirken Policies oft anders als ihr „natürlichsprachliches“ Ziel vermuten lässt. Zweitens erzeugen KI-Vorschläge schnell ausreichend plausibles SQL, ohne dass die tatsächliche Autorisierungssemantik verstanden wurde.
Ein viertes häufiges Praxisproblem ist das vermeintlich „kaputte“ service_role-Verhalten. Supabase hat dafür inzwischen sogar einen eigenen Troubleshooting-Artikel: Ein Client mit Authorization auf service_role umgeht RLS immer.[17] Wenn Teams trotzdem RLS-Fehler sehen, liegt der Grund oft darin, dass in SSR-Umgebungen, Edge Functions oder gemischten Auth-Flows der Authorization-Header durch eine User-Session oder ein User-JWT überschrieben wurde. Der Effekt ist tückisch: Das Team glaubt, es teste einen Admin-Client, tatsächlich testet es einen normalen Benutzerkontext.
Und noch ein sehr häufiger Support-Fall: Leere Arrays statt Fehlermeldung. Supabase dokumentiert, dass eine select()-Abfrage mit leerem Ergebnis bei vorhandenen Daten oft schlicht bedeutet, dass RLS aktiviert ist und keine passende Policy greift oder keine Zeile die Filterbedingung erfüllt.[18] Für Gründerteams ist das wichtig, weil ein „scheinbar harmloses“ leeres Ergebnis genauso gut auf eine kaputte Autorisierung wie auf fehlende Daten hinweisen kann. Ohne systematisches Testen wird daraus schnell Debugging nach Gefühl.
Best Practices für sichere RLS
Die sicherste Grundhaltung ist die, die OWASP seit Jahren empfiehlt: Least Privilege, deny by default, Berechtigungen auf jeder Anfrage prüfen und Autorisierungslogik testen.[8] Für Supabase heißt das konkret: nur die Tabellen exponieren, die wirklich vom Client erreichbar sein müssen; nur die Rollen und Operationen erlauben, die das Produkt braucht; und bei jeder neuen Funktion fragen, welche konkreten Zeilen welcher Nutzer sehen oder verändern darf. RLS sollte keine Ansammlung von Ausnahmen sein, sondern die präzise Beschreibung Ihrer Geschäftsregeln.
Praktisch bewährt sich ein einfaches Muster: Identität an auth.uid(), Rollen an app_metadata oder eigene Tabellen, nie an user_metadata. Supabase empfiehlt zudem, bei auth.uid() die Authentifizierung explizit zu prüfen, weil unauthentifizierte Requests null zurückgeben. Für viele Anwendungen ist das ein sauberer Startpunkt:
create policy "Users manage own rows"
on public.documents
for all
to authenticated
using (
auth.uid() is not null
and auth.uid() = owner_id
)
with check (
auth.uid() is not null
and auth.uid() = owner_id
);Das ist kein Universalmuster für jede App, aber es ist ein solides Default-Muster für „eigene Datensätze pro Nutzer“. Sobald Sie Teams, Rechtehierarchien oder Delegation haben, sollten Sie auf klar definierte Rollenmodelle oder ReBAC/ABAC-artige Beziehungen umsteigen. OWASP empfiehlt dafür ausdrücklich attribut- und beziehungsbasierte Autorisierung dort, wo einfaches RBAC zu grob wird.[8]
Für serverseitige Admin-Aktionen gilt: Admin-Zugriff sauber trennen, nie mischen. Secret Keys und service_role umgehen RLS und gehören ausschließlich in kontrollierte Backend-Komponenten.[6] Verwenden Sie dafür getrennte Clients und separate Geheimnisse pro Service. Supabase empfiehlt Secret Keys als modernere Form des erhöhten Backend-Zugriffs und warnt ausdrücklich davor, Service- oder Secret-Keys im Frontend zu verwenden oder im Quellcode offenzulegen.
Achten Sie außerdem auf die Angriffsfläche Ihrer API. Supabase empfiehlt, wenn sinnvoll, ein dediziertes API-Schema zu verwenden statt pauschal das public-Schema zu exponieren.[5] Wenn Ihre Anwendung die Data API gar nicht braucht, können Sie sie komplett deaktivieren. Für Funktionen gilt: RLS schützt nicht die Funktionsausführung selbst; Sie müssen EXECUTE-Rechte bewusst vergeben und SECURITY DEFINER-Funktionen sehr kritisch prüfen.[5] Das ist besonders relevant, wenn KI Ihnen „bequeme“ RPC-Helfer generiert, die versteckt mehr dürfen als Ihr Frontend eigentlich sollte.
Zur Absicherung gehört schließlich Testen als eigener Arbeitsschritt, nicht als Bauchgefühl. Supabase empfiehlt automatisierte Tests für Datenbankschema und RLS und unterstützt dafür pgTAP sowie supabase test db.[10] Für produktive Projekte sollten Sie mindestens folgende Fälle automatisch testen: anonymer Zugriff, normaler eingeloggter Zugriff, Cross-Tenant-Zugriff, Rollenwechsel, Admin-Zugriff, Inserts/Updates mit fremden IDs sowie Regressionen nach Schemaänderungen. Ergänzend dazu sollten Sie Security Advisor und Performance Advisor regelmäßig laufen lassen; Supabase nennt dort explizit Checks für fehlende Indexe, RLS ohne Policy, Policy trotz deaktivierter RLS, user-metadata-basierte RLS, security-definer views und breite permissive Policies.[11]
Performance ist dabei kein Nebenthema. Supabase weist darauf hin, dass RLS jede Autorisierungsabfrage in die Query-Planung einbezieht.[19] Die Dokumentation empfiehlt deshalb, Spalten zu indexieren, die in Policies verwendet werden, Funktionen und bestimmte Ausdrücke bei Bedarf in select zu kapseln und zusätzlich normale Query-Filter zu setzen, statt sich nur auf „implizite where clauses“ zu verlassen. Sonst wächst in schnell gebauten Apps oft der Druck, RLS „vorübergehend“ zu entschärfen, weil Abfragen zu langsam werden. Genau diesem Shortcut sollten Sie widerstehen.
Ein besonders nützlicher Praxischeck vor jedem Release lautet deshalb:
- Ist für jede exponierte Tabelle oder jedes exponierte View RLS bewusst entworfen und aktiviert?[4][5]
- Verwendet keine Policy benutzerveränderbare
user_metadataals Autorisierungsquelle?[4] - Liegen keine
SECURITY DEFINER-Funktionen in exponierten Schemas, die direkt aufrufbar sind?[5] - Sind Secret- oder Service-Keys strikt backend-only und pro Dienst getrennt?[6]
- Laufen automatische RLS-Tests und Security-Advisor-Checks im Release-Prozess?[10][11]
Wann rechtliche oder technische Beratung sinnvoll ist
Technische Beratung ist sinnvoll, sobald Ihre App mehr ist als „jeder Nutzer sieht nur seine eigenen Notizen“. Dazu gehören Multi-Tenant-SaaS, B2B-Adminbereiche, rollenbasierte Workflows, Teammitgliedschaften, Einladungslogik, Delegation, Support-Zugriffe, freigegebene Datensätze, Billing-/Quota-Gates, RPC-Funktionen mit erhöhten Rechten, Realtime-/Storage-Autorisierung und jede Architektur, in der SECURITY DEFINER, custom claims oder serverseitige Jobs ins Spiel kommen.[4][5][14][15][17] Spätestens wenn Sie diskutieren, ob ein View, eine Funktion oder ein JWT-claim „wohl schon okay“ ist, lohnt sich ein gezielter Security-Review.
Rechtliche Beratung ist angebracht, wenn Sie personenbezogene Daten, besonders sensible Daten oder regulierte Daten verarbeiten, etwa im Gesundheits-, Finanz-, Bildungs-, HR- oder B2B-Compliance-Kontext. Datenschutzrecht verlangt in vielen Märkten nicht irgendeine Sicherheit, sondern angemessene technische und organisatorische Maßnahmen. Im europäischen Kontext verlangt Artikel 32 DSGVO fortlaufende Vertraulichkeit, Integrität, Verfügbarkeit und einen Prozess zur regelmäßigen Prüfung der Wirksamkeit von Schutzmaßnahmen.[9] Die britische ICO formuliert ähnlich, dass geeignete technische und organisatorische Maßnahmen risikobasiert auszuwählen sind. RLS kann dabei ein starker Baustein sein, aber nicht allein Ihre Compliance begründen. Diese Passage ist Informationsmaterial, keine Rechtsberatung.
Besonders wichtig ist professionelle Hilfe auch nach größeren Änderungen: wenn neue Tabellen entstehen, ein Reporting-Layer dazukommt, Admin- oder Backoffice-Prozesse ergänzt werden, alte Policies umgeschrieben werden oder Sie von einfachen Nutzer-zu-Daten-Beziehungen auf Teams und Organisationen umstellen. Gerade dort schlägt „verification debt“ von KI-generiertem Code zu: Die Architektur wirkt fertig, aber die Autorisierungslogik ist nie durchdacht worden. Die aktuelle Marktlage mit hoher KI-Nutzung und gleichzeitig geringer Vertrauensbasis in die Genauigkeit der Ausgaben spricht klar dafür, Sicherheitslogik bewusst zu reviewen statt sie implizit zu übernehmen.[3][12][13]
Fazit
Supabase macht es angenehm einfach, Daten direkt aus dem Client zu lesen und zu schreiben. Genau deshalb muss RLS in Ihrer App bewusst konzipiert, getestet und gepflegt werden. Die größten Risiken entstehen selten aus komplizierter Kryptographie; sie entstehen durch scheinbar kleine Abkürzungen: eine nicht aktivierte Policy, ein zu breites USING (true), ein View im public-Schema, eine Rolle in user_metadata, ein geleakter Admin-Key oder ein SSR-Client, der unbemerkt in den falschen Auth-Kontext rutscht.[4][5][11][14][17]
Für Gründer und Entwickler ist die pragmatische Leitlinie einfach: Wenn Sie erklären können, wer welche Zeile warum sehen darf, wenn diese Regeln automatisiert testbar sind und wenn Ihre Backendschlüssel strikt getrennt bleiben, sind Sie auf einem deutlich besseren Weg als viele schnell zusammengesetzte Apps. Wenn Sie das nicht sicher erklären können, ist genau jetzt der richtige Zeitpunkt für eine technische Prüfung, bevor Ihre Nutzer, Kunden oder Aufsichtsbehörden die Lücken für Sie entdecken.[7][8]
References
Click any inline citation to jump to its matching source entry.
- [1]Stack Overflow. "Stack Overflow Developer Survey 2025: AI Tools Adoption & Sentiment." Stack Overflow.
- [2]Lovable. " Lovable CVE-2025-48757: Auditing Lovable projects database security." Lovable Blog.
- [3]GitHub. "Octoverse 2025: State of Open Source and AI Adoption." GitHub Blog.
- [4]Supabase. "Row Level Security in Supabase." Supabase Docs.
- [5]Supabase. "Securing your Supabase API." Supabase Docs.
- [6]PostgreSQL. "Row Security Policies and CREATE POLICY." PostgreSQL Documentation.
- [7]OWASP. "Authorization Cheat Sheet." OWASP Foundation.
- [8]Intersoft Consulting. "General Data Protection Regulation (GDPR) Article 32: Security of processing." GDPR-Info.
- [9]Supabase. "Testing your Supabase database." Supabase Docs.
- [10]Supabase. "Database Security and Performance Advisors." Supabase Docs.
- [11]Supabase. "Understanding Supabase API Keys and Auth Roles." Supabase Docs.
- [12]Supabase. "Views and Row-Level Security in Postgres." Supabase Docs.
- [13]Supabase. "Materialized Views and RLS." Supabase Docs.
- [14]Supabase. "Supabase Community Discussions on RLS Update Policies." GitHub Discussions.
- [15]Supabase. "Auth Troubleshooting: Service Role and SSR Session Overrides." Supabase Help.
- [16]Supabase. "RLS Troubleshooting: Empty array results." Supabase Docs.
- [17]Supabase. "Row Level Security Performance Tuning." Supabase Docs.
Passende nächste Schritte
Vertiefen Sie das Thema mit den wichtigsten Service- und Projektseiten.




