Su­pa­ba­se Row Le­vel Se­cu­ri­ty: War­um sie die Zu­griffs­kon­trol­le ver­än­dert

Row Le­vel Se­cu­ri­ty ver­la­gert die Zu­griffs­kon­trol­le aus dem An­wen­dungs­code in die Da­ten­bank. Da­mit ver­schwin­det der ver­ges­se­ne Fil­ter als Feh­ler­klas­se struk­tu­rell statt durch Dis­zi­plin. Für Mehr­man­dan­ten-SaaS ist das eine Ri­si­ko- und Ge­schwin­dig­keits­fra­ge auf Ent­schei­der­ebe­ne.
6 Min. LesezeitMatthias RadscheitMatthias Radscheit
Happycodingde-DE

TL;DR

Supabase Row Level Security verlagert die Zugriffskontrolle aus der Anwendungsschicht in Postgres. Die Regel wird einmal als Policy geschrieben und gilt für jeden Client, auch wenn ein Entwickler den Filter im Code vergisst. Für Mehrmandanten-SaaS eliminiert das eine ganze Fehlerklasse strukturell und beschleunigt zugleich die Entwicklung.

  • RLS macht die Zugriffsregel zur Eigenschaft der Tabelle, nicht zur Verantwortung jedes einzelnen Endpoints. Der vergessene Filter wird strukturell unmöglich.
  • Für Multitenancy-SaaS bilden Policies Organisationen und Rollen direkt in der Datenbank ab. Nutzer aus Firma A sehen nie Daten von Firma B, ohne eine Zeile Middleware.
  • Neue Features erben die Zugriffskontrolle aus der DB-Schicht. Das reduziert Boilerplate und beschleunigt die Entwicklung, statt sie zu bremsen.
  • RLS ist kein Allheilmittel: Der service_role-Key und SECURITY-DEFINER-Funktionen umgehen RLS vollständig, falsch geschriebene Policies öffnen zu viel oder zu wenig.
  • RLS ab Tag 1 aktivieren. Nachträglich eingebaute Sicherheit ist teurer und unzuverlässiger als von Anfang an.

Die meis­ten Da­ten­lecks in Mehr­man­dan­ten-An­wen­dun­gen ent­ste­hen nicht durch aus­ge­feil­te An­grif­fe, son­dern durch eine ver­ges­se­ne Zei­le. Ein Ent­wick­ler baut ei­nen neu­en End­point, schreibt die Que­ry und ver­gisst das whe­re user_id = .... Ab die­sem Mo­ment sieht Nut­zer A die Da­ten von Nut­zer B.

Ge­nau hier setzt Su­pa­ba­se Row Le­vel Se­cu­ri­ty an. Statt die Zu­griffs­kon­trol­le in je­dem End­point neu zu for­mu­lie­ren, sitzt sie als Re­gel im Fun­da­ment der Da­ten­bank. Das klingt nach ei­nem Ent­wick­ler­de­tail. Es ist in Wirk­lich­keit eine Ent­schei­dung über Ri­si­ko und Ent­wick­lungs­ge­schwin­dig­keit, und sie ge­hört auf den Tisch von CIOs und CTOs, nicht nur in den Pull Re­quest.

Was Su­pa­ba­se Row Le­vel Se­cu­ri­ty struk­tu­rell än­dert

Die klas­si­sche Ant­wort auf Man­dan­ten­tren­nung ist Midd­le­wa­re. Ein Ba­ckend-End­point prüft die User-ID, fil­tert jede Que­ry, und das wie­der­holt sich für je­den neu­en End­point. Die­ser An­satz ist feh­ler­an­fäl­lig, schwer test­bar und muss bei je­dem Fea­ture neu durch­dacht wer­den. Die Si­cher­heit hängt an der Dis­zi­plin je­des ein­zel­nen Ent­wick­lers an je­dem ein­zel­nen Tag. Ein ver­ges­se­ner Fil­ter ge­nügt für ein Da­ten­leck.

RLS dreht das Mo­dell um. Die Zu­griffs­re­gel wird ein­mal als Po­li­cy auf ei­ner Ta­bel­le ge­schrie­ben, und Post­gres er­zwingt sie da­nach für je­den Cli­ent au­to­ma­tisch. Auch dann, wenn ein Ent­wick­ler den Fil­ter im An­wen­dungs­code ver­gisst. Aus sel­ect whe­re user_id = ak­tu­el­ler­Nut­zer in je­dem End­point wird eine ein­zi­ge Re­gel in der Da­ten­bank.

Ein kon­kre­tes Bei­spiel. Eine Pro­jekt­ma­nage­ment-App, je­der Nut­zer soll nur sei­ne ei­ge­nen Pro­jek­te se­hen. Sie ak­ti­vie­ren RLS auf der Ta­bel­le und schrei­ben eine Po­li­cy, die fest­legt: Eine Zei­le ist nur sicht­bar, wenn ihre user_id der ID des an­ge­mel­de­ten Nut­zers ent­spricht. Ab die­sem Mo­ment ist die Zu­griffs­kon­trol­le eine Ei­gen­schaft der Ta­bel­le, nicht eine Ver­ant­wor­tung des nächs­ten End­points. Wer wis­sen will, was Su­pa­ba­se dar­un­ter über­haupt ist, fin­det das im Grund­la­gen­ar­ti­kel Was ist Su­pa­ba­se?.

Der ent­schei­den­de Punkt für Ent­schei­der: Eine gan­ze Feh­ler­klas­se ver­schwin­det. Nicht weil das Team dis­zi­pli­nier­ter ar­bei­tet, son­dern weil die Da­ten­bank den Feh­ler struk­tu­rell nicht mehr zu­lässt. Das ist der Un­ter­schied zwi­schen "wir ach­ten dar­auf" und "es kann nicht pas­sie­ren".

War­um RLS Post­gres die rich­ti­ge Ebe­ne für Zu­griffs­kon­trol­le ist

RLS ist kein Su­pa­ba­se-Fea­ture, son­dern eine na­ti­ve Funk­ti­on von Post­gres. Su­pa­ba­se macht sie nur kom­for­ta­bel nutz­bar und ver­drah­tet sie mit der Au­then­ti­fi­zie­rung. Die Zu­griffs­re­gel läuft da­mit auf der­sel­ben Ebe­ne wie die Da­ten selbst, aus­ge­wer­tet vom Que­ry-Pla­ner.

Das hat eine Kon­se­quenz, die in Ar­chi­tek­tur-Dis­kus­sio­nen oft un­ter­geht: Es gibt kei­nen Um­weg an der Re­gel vor­bei. Egal ob die Ab­fra­ge aus dem Web-Front­end, ei­ner mo­bi­len App oder ei­nem Dritt­sys­tem kommt, sie trifft die­sel­be Po­li­cy. Die Post­gres-Do­ku­men­ta­ti­on zu CREA­TE PO­LI­CY be­schreibt das Ver­hal­ten prä­zi­se: Die Be­din­gung wird als zu­sätz­li­ches Prä­di­kat in jede Ab­fra­ge ein­ge­baut, trans­pa­rent für den Cli­ent.

Für die Zu­griffs­kon­trol­le in der Da­ten­bank be­deu­tet das eine an­de­re Ver­trau­ens­gren­ze. Bei rei­ner An­wen­dungs­lo­gik ver­trau­en Sie dar­auf, dass je­der Pfad zur Da­ten­bank die Fil­ter kor­rekt setzt. Bei RLS ver­trau­en Sie der Da­ten­bank, und die An­wen­dung kann den Fil­ter gar nicht mehr um­ge­hen, so­lan­ge sie mit dem nor­ma­len Nut­zer-To­ken ar­bei­tet. Die Si­cher­heit wird von ei­ner Ei­gen­schaft des Codes zu ei­ner Ei­gen­schaft des Da­ten­mo­dells.

Was RLS für Ent­schei­der kon­kret be­deu­tet

Drei Ef­fek­te sind re­le­vant, wenn Sie eine In­ves­ti­ti­ons­ent­schei­dung recht­fer­ti­gen müs­sen.

Ers­tens, we­ni­ger Bugs und struk­tu­rell we­ni­ger Si­cher­heits­ri­si­ko. Der ver­ges­se­ne Fil­ter wird un­mög­lich, nicht un­wahr­schein­lich. Das ist ein Ar­gu­ment, das vor ei­nem Vor­stand trägt, weil es eine Aus­sa­ge über die Ar­chi­tek­tur ist, nicht über die Sorg­falt ei­nes Teams.

Zwei­tens, schnel­le­re Ent­wick­lung. Neue Fea­tures er­ben die Zu­griffs­kon­trol­le aus der Da­ten­bank­schicht. Das Team schreibt we­ni­ger Boi­ler­p­la­te, und je­der neue End­point ist von An­fang an ab­ge­si­chert, ohne dass je­mand dar­an den­ken muss. Si­cher­heit als Stan­dard­zu­stand statt als Zu­satz­auf­ga­be be­schleu­nigt die Aus­lie­fe­rung mess­bar.

Drit­tens, Ska­lie­rung. Die­sel­be Po­li­cy gilt für zehn wie für hun­dert­tau­send Nut­zer. Es gibt kei­ne wach­sen­de Ma­trix aus End­points und Fil­ter­be­din­gun­gen, die mit dem Er­folg des Pro­dukts mit­wächst und mit­kippt. Das Ope­ra­ting Mo­del bleibt über die Zeit sta­bil.

Man­dan­ten­fä­hig­keit ohne eine Zei­le Midd­le­wa­re

Der Punkt, an dem RLS am deut­lichs­ten wird, ist Man­dan­ten­fä­hig­keit. Ein ty­pi­sches Mul­ti­ten­an­cy-SaaS hat Or­ga­ni­sa­tio­nen, in de­nen Nut­zer mit Rol­len sit­zen, etwa Ow­ner, Ad­min und Mem­ber. Die­se Struk­tur lässt sich di­rekt in Po­li­ci­es ab­bil­den.

Eine Zei­le ge­hört zu ei­ner Or­ga­ni­sa­ti­on, ein Nut­zer ge­hört über eine Zwi­schen­ta­bel­le zu ei­ner oder meh­re­ren Or­ga­ni­sa­tio­nen, und die Po­li­cy ver­knüpft bei­des: Sicht­bar ist eine Zei­le nur, wenn der an­ge­mel­de­te Nut­zer Mit­glied der zu­ge­hö­ri­gen Or­ga­ni­sa­ti­on ist. Rol­len kom­men als zu­sätz­li­che Be­din­gung dazu, wenn etwa nur Ad­mins be­stimm­te Da­ten­sät­ze än­dern dür­fen.

Das Er­geb­nis ist eine har­te Man­dan­ten­tren­nung: Nut­zer aus Fir­ma A se­hen nie Da­ten von Fir­ma B. Die­se Ga­ran­tie liegt nicht in ei­ner Midd­le­wa­re-Schicht, die je­mand pfle­gen, tes­ten und bei je­dem Fea­ture er­neut kor­rekt ver­drah­ten muss, son­dern in der Da­ten­bank. Für ein SaaS-Pro­dukt, des­sen gan­zes Ge­schäfts­mo­dell auf der Tren­nung der Kun­den­da­ten be­ruht, ist das der prag­ma­tischs­te und zu­gleich si­chers­te Weg, den ich ken­ne.

Wer von Fire­ba­se kommt, soll­te ei­nen Punkt ein­pla­nen. In Su­pa­ba­se er­setzt RLS die Fires­to­re Se­cu­ri­ty Ru­les, aber die Mo­del­le sind nicht de­ckungs­gleich. Fires­to­re-Re­geln sind pfad­ba­siert, RLS sind SQL-Po­li­ci­es pro Ta­bel­le. Das ist ein Neu­den­ken des Si­cher­heits­mo­dells, kein Su­chen-und-Er­set­zen, und ge­nau die­sen Schritt un­ter­schät­zen Teams bei der Mi­gra­ti­on von Fire­ba­se zu Su­pa­ba­se re­gel­mä­ßig.

Wo RLS kein All­heil­mit­tel ist

Wer RLS als Si­cher­heits­ga­ran­tie ver­kauft, hat es nicht ver­stan­den. Es nimmt eine be­stimm­te Feh­ler­klas­se aus dem Spiel, aber es er­öff­net an­de­re, wenn man un­auf­merk­sam ist.

Po­li­ci­es müs­sen durch­dacht sein. Eine falsch ge­schrie­be­ne Po­li­cy er­laubt zu viel oder zu we­nig, und bei­des fällt oft erst spät auf. Zu viel be­deu­tet ein Da­ten­leck, zu we­nig be­deu­tet eine ka­put­te An­wen­dung. Po­li­ci­es ge­hö­ren des­halb ge­tes­tet, am bes­ten mit Ne­ga­tiv­tests, die be­le­gen, dass ein Nut­zer eben nicht sieht, was er nicht se­hen darf.

Zwei Me­cha­nis­men um­ge­hen RLS be­wusst, und bei­de muss man ken­nen. SE­CU­RI­TY-DE­FI­NER-Funk­tio­nen, in Su­pa­ba­se als RPCs auf­ge­ru­fen, lau­fen mit den Rech­ten des De­fi­nie­rers und kön­nen RLS ge­zielt aus­he­beln. Das ist manch­mal ge­nau ge­wollt, etwa für ad­mi­nis­tra­ti­ve Ope­ra­tio­nen, aber es muss kon­trol­liert und sicht­bar ein­ge­setzt wer­den. Der ser­vice_role-Key um­geht RLS voll­stän­dig. Er ist für ser­ver­sei­ti­ge Auf­ga­ben ge­dacht und darf nie­mals ins Front­end ge­lan­gen. Ein ser­vice_role-Key im Brow­ser-Code ist der schwer­wie­gends­te Feh­ler, den man mit Su­pa­ba­se ma­chen kann, und er macht jede Po­li­cy wert­los. Die Su­pa­ba­se-Do­ku­men­ta­ti­on zu Row Le­vel Se­cu­ri­ty ist an die­ser Stel­le ein­deu­tig.

Au­ßer­dem er­setzt RLS kei­ne Ein­ga­be­va­li­die­rung. Es ent­schei­det, wer wel­che Zei­len sieht und än­dert, nicht ob die Ein­ga­ben ei­ner Ge­schäfts­lo­gik ge­nü­gen. Und kom­ple­xe Po­li­ci­es kön­nen Per­for­mance kos­ten, wenn pro Zei­le teu­re Un­ter­ab­fra­gen aus­ge­wer­tet wer­den. Das ist be­herrsch­bar, aber es ist eine De­sign­auf­ga­be, kein Selbst­läu­fer.

Was ich Ent­schei­dern rate

Ak­ti­vie­ren Sie RLS ab Tag 1, auch mit ein­fa­chen Po­li­ci­es. Nach­träg­lich ein­ge­bau­te Si­cher­heit ist im­mer teu­rer und un­zu­ver­läs­si­ger als von An­fang an mit­ge­dach­te. Eine Ta­bel­le ohne ak­ti­vier­tes RLS in ei­nem Man­dan­ten-Sys­tem ist eine of­fe­ne Tür, und je län­ger das Sys­tem läuft, des­to mehr Code stützt sich auf die­se of­fe­ne Tür.

Be­han­deln Sie die Fra­ge nicht als Im­ple­men­tie­rungs­de­tail des Ent­wick­lungs­teams, son­dern als Ar­chi­tek­tur­ent­schei­dung mit di­rek­ter Wir­kung auf Ven­dor Risk, Com­pli­ance und Aus­lie­fe­rungs­ge­schwin­dig­keit. RLS ver­schiebt die Ver­trau­ens­gren­ze an die rich­ti­ge Stel­le: in die Da­ten­bank, wo die Da­ten oh­ne­hin lie­gen. Das ist kein Zau­ber­trick, der Ein­ga­be­va­li­die­rung, sau­be­re Schlüs­sel­ver­wal­tung und ge­tes­te­te Po­li­ci­es er­setzt. Aber es nimmt Ih­nen die teu­ers­te und pein­lichs­te Feh­ler­klas­se struk­tu­rell ab, und das ist mehr, als die meis­ten Si­cher­heits­maß­nah­men leis­ten. Wer die Platt­form als Gan­zes be­wer­tet, soll­te RLS als ei­nen der Grün­de ver­bu­chen, war­um sich Su­pa­ba­se für ernst­haf­te Mehr­man­dan­ten-Pro­duk­te rech­net, wie wir es in un­se­rer Ein­ord­nung als Su­pa­ba­se-Agen­tur aus­füh­ren.

Häufige Fragen

Ersetzt RLS die Zugriffskontrolle in der Anwendung vollständig?
Nein. RLS erzwingt zeilenbasierte Zugriffsregeln in der Datenbank und nimmt damit die größte Fehlerklasse aus dem Anwendungscode. Eingabevalidierung, Geschäftslogik und die Absicherung von Server-Pfaden mit dem service_role-Key bleiben Aufgabe der Anwendung. RLS ist die robuste Basisschicht, nicht das komplette Sicherheitskonzept.
Wie unterscheidet sich RLS von den Firestore Security Rules?
Firestore-Regeln sind pfadbasiert und in einer eigenen Regelsprache geschrieben. RLS sind SQL-Policies pro Tabelle, ausgewertet direkt in Postgres. Bei einer Migration von Firebase zu Supabase ist das ein Neudenken des Sicherheitsmodells, kein Suchen-und-Ersetzen. Die Logik wird relational statt dokumentenorientiert formuliert.
Kostet RLS Performance?
Einfache Policies sind in der Praxis kaum messbar, weil Postgres die Bedingung als zusätzliches Prädikat in die Query einbaut. Komplexe Policies mit Unterabfragen oder Funktionsaufrufen pro Zeile können teuer werden. Beides ist beherrschbar durch passende Indizes und das Bündeln von Berechtigungslogik in stabilen Funktionen.
Was passiert, wenn der service_role-Key ins Frontend gelangt?
Der service_role-Key umgeht RLS vollständig und gibt vollen Lese- und Schreibzugriff auf alle Daten. Er gehört ausschließlich in serverseitige Umgebungen und niemals in Browser-Code oder mobile Apps. Das ist die wichtigste operative Regel beim Arbeiten mit RLS und der häufigste schwerwiegende Fehler.

Quellen

Ähnliche Artikel

Offen für ausgewählte Projekte

Lassen Sie uns über Ihr Projekt sprechen

Bu­chen Sie ei­nen un­ver­bind­li­chen Ter­min, schrei­ben Sie uns eine E-Mail oder nut­zen Sie das For­mu­lar – wir freu­en uns auf Ihre Nach­richt.

150+
Abgeschlossene Projekte
15
Jahre Erfahrung
8
Senior‑Level Teammitglieder