Kurz gesagt
Der anon key, jetzt publishable key genannt, ist dafür gedacht, öffentlich zu sein: Er gehört zur Rolle anon oder authenticated, und Ihre RLS-Policies entscheiden, was er sieht. Der service role key, jetzt secret key, gehört zu service_role, und die umgeht RLS vollständig. Auf meiner lokalen Testtabelle mit RLS an und ohne Policy bekam der öffentliche Key 0 Zeilen und der Secret Key alle 3. Der publishable key gehört in den Browser, der secret key auf einen Server, und wurde er je ausgeliefert, rotieren Sie ihn.
Ich bin Denys, Full-Stack- und KI-Entwickler. Ein geleakter secret key ist das Erste, wonach ich suche, wenn ich eine Supabase-App übernehme, denn mit ihm ist jeder andere Schutz Dekoration. Dieser Artikel erklärt, was jeder Key öffnet, mit den Anfragen, mit denen ich es geprüft habe.
Was ist der Supabase anon key?
Der anon key identifiziert Ihre App, nicht Ihren Nutzer. Jede Anfrage aus einem Browser oder einer mobilen App trägt ihn, er muss also öffentlich sein: Jeder kann ihn aus dem Seitenquelltext lesen. Eine Anfrage nur mit diesem Key läuft als Postgres-Rolle anon. Meldet sich ein Nutzer über Supabase Auth an, reist derselbe Key mit dem Token des Nutzers, und die Anfrage läuft als authenticated. Ihre RLS-Policies sind für diese beiden Rollen geschrieben.
Supabase benennt die Keys um. Der API-Keys-Leitfaden nennt die neuen publishable (sb_publishable_…) und secret (sb_secret_…) und stellt die alten JWT-basierten Keys anon und service_role bis Ende 2026 ein. Die Rollen dahinter bleiben dieselben.
| Key | Alter Name | Postgres-Rolle | Gilt RLS? | Wohin damit |
|---|---|---|---|---|
Publishable sb_publishable_… |
anon key |
anon, oder authenticated mit Nutzer-Token |
Ja | Browser, mobile App, alles, was Sie ausliefern |
Secret sb_secret_… |
service_role key |
service_role |
Nein, die Rolle hat BYPASSRLS |
Nur Server, Edge Function, Cron-Job |
Ist es sicher, den Supabase anon key offenzulegen?
Ja, wenn jede Tabelle, View und Funktion, die er erreicht, geschützt ist. Der Key selbst gibt nichts Besonderes frei; Grants und Policies in Ihrem Schema entscheiden alles. Ich habe das auf einem lokalen Supabase-Stack (CLI 2.109.1, Postgres 17.6) mit einer Tabelle mit drei erfundenen Bestellungen geprüft:
| Zustand der Tabelle | Publishable key | Secret key |
|---|---|---|
| RLS aus | Alle 3 Zeilen, und ein Insert lieferte 201 Created |
Alle 3 Zeilen |
| RLS an, keine Policy | [] |
Alle 3 Zeilen |
RLS an, Policy using (true) |
Alle 3 Zeilen | Alle 3 Zeilen |
Kein Grant für anon |
42501 permission denied, mit einem Hinweis, der den fehlenden GRANT nennt |
Alle 3 Zeilen |
Der publishable key ist also genau so sicher wie Ihre schwächste Tabelle. Eine Tabelle ohne RLS oder mit einer Policy, die jede Zeile erlaubt, kann jeder lesen, der DevTools öffnet. Das ist die Lücke hinter CVE-2025-48757, bei der 170 von 1.645 Lovable-Showcase-Apps Daten an den öffentlichen Key lieferten.
Was ist der service role key, und warum ist er gefährlich?
Der secret key ist der Generalschlüssel. Er läuft als service_role, und die hat das Attribut BYPASSRLS, sodass keine Policy, die Sie schreiben, je für ihn gilt. In der letzten Spalte der Tabelle oben las er in jedem Zustand alle drei Zeilen. Der Leitfaden von Supabase nennt, wohin er gehört: Server, die eigene Autorisierungsprüfungen ausführen, Edge Functions, Hintergrund-Jobs und Admin-Tools. Zwei Details aus dem Leitfaden zählen in der Praxis:
- Der neue secret key lehnt Browser-Anfragen ab: Supabase gleicht den
User-Agentab und liefert401. Das alteservice_role-JWT hat keine solche Prüfung, ein geleakter alter Key funktioniert also von überall. Mein lokaler Stack, der keine solche Gateway-Prüfung hat, beantwortete ein Skript mit dem secret key mit allen 3 Zeilen. - Ein secret key umgeht RLS nur, wenn die Anfrage kein Nutzer-Token trägt. Mit dem Token eines angemeldeten Nutzers läuft die Anfrage unter den Policies dieses Nutzers.
Eine Edge Function, die den secret key nutzt, muss selbst prüfen, wer aufruft, und selbst nach Besitzer oder Firma filtern, denn darunter tut es nichts mehr.
Wo finden Sie die Keys?
Öffnen Sie im Dashboard den Connect-Dialog Ihres Projekts für die URL und den publishable key, oder Settings → API Keys für alle Keys, auch die alten. Lokal geben supabase start und supabase status einen publishable key und einen secret key aus. Halten Sie sie in Umgebungsvariablen: In Next.js darf nur der publishable key das Präfix NEXT_PUBLIC_ tragen, denn der Bundler liefert alles mit diesem Präfix an den Browser aus.
Was tun, wenn der service role key geleakt wurde?
Behandeln Sie ihn als kompromittiert: Jede Zeile in jeder Tabelle war für den Finder les- und schreibbar.
- Erstellen Sie einen neuen secret key, stellen Sie Ihre Server darauf um und löschen Sie dann den geleakten. War es ein alter
service_rolekey, ist der Ausweg der Umstieg auf die neuen Keys: einen publishable und einen secret key anlegen, die App umstellen und dann die alten Keys unter Settings → API Keys deaktivieren, wo sie sonst gültig bleiben. - Durchsuchen Sie das gebaute JavaScript und die Git-Historie nach
sb_secret_undservice_role. Escapes Scan von 5.600 vibe-codierten Apps fand über 400 offengelegte Secrets, die meisten in Frontend-Bundles. - Prüfen Sie, was sich geändert hat, solange er draußen war: neue Nutzer, Rollenänderungen, gelöschte Zeilen.
Der kostenlose Supabase-Sicherheitscheck liest Ihr Frontend nicht, aber er liest die Datenbankseite desselben Problems: Rollen, die RLS umgehen, Tabellen mit RLS aus, Policies, die jede Zeile erlauben, und Spalten, die sensibel aussehen und für anonyme Besucher lesbar sind. Wie Sie prüfen, was Ihr öffentlicher Key in der Praxis erreicht, steht in Vibe Coding Sicherheitsrisiken, und die ganze Liste, die ich bei einer App durchgehe, steht in meiner Sicherheits-Checkliste für Lovable-Apps.
Unsicher, welchen Key Ihre App ausliefert?
Ich schaue gern drauf und tausche mich aus. Ohne Verkaufsgespräch.
Kontakt aufnehmen