---
title: "Supabase anon key vs service role key: was jeder öffnet"
description: "Der Supabase anon key (publishable key) ist im Browser nur hinter RLS sicher; der service role key (secret key) umgeht sie. Lokal getestet."
url: "https://madsalt.tech/de/blog/supabase-anon-key-vs-service-role-key/"
author: "Denys Zaichenko"
language: "de"
published: 2026-10-25
---

# Supabase anon key vs service role key: was jeder öffnet

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](https://supabase.com/docs/guides/api/api-keys) 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:

![Zu welcher Postgres-Rolle jeder Key wird. Und ob Ihre RLS-Policies die Anfrage sehen. Publishable key, abgemeldet: Publishable key → Rolle anon → RLS-Policies greifen; Publishable key, angemeldet: Publishable key + Nutzer-Token → Rolle authenticated → RLS-Policies greifen; Secret key: Secret key → Rolle service_role → RLS übersprungen.](https://madsalt.tech/charts/de/supabase-anon-key-vs-service-role-key.svg)

*Abbildung 1. Aus dem Supabase-Leitfaden zu API-Keys, auf einem lokalen Stack geprüft, 23. Oktober 2026.*

| 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](https://mattpalmer.io/posts/2025/05/statement-on-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-Agent` ab und liefert `401`. Das alte `service_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.

1. Erstellen Sie einen neuen secret key, stellen Sie Ihre Server darauf um und löschen Sie dann den geleakten. War es ein alter `service_role` key, 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.
2. Durchsuchen Sie das gebaute JavaScript und die Git-Historie nach `sb_secret_` und `service_role`. Escapes Scan von 5.600 vibe-codierten Apps fand [über 400 offengelegte Secrets](https://escape.tech/blog/methodology-how-we-discovered-vulnerabilities-apps-built-with-vibe-coding/), die meisten in Frontend-Bundles.
3. Prüfen Sie, was sich geändert hat, solange er draußen war: neue Nutzer, Rollenänderungen, gelöschte Zeilen.

Der kostenlose [Supabase-Sicherheitscheck](https://madsalt.tech/de/tools/supabase-security-check/) 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](https://madsalt.tech/de/blog/vibe-coding-security-risks/), und die ganze Liste, die ich bei einer App durchgehe, steht in meiner [Sicherheits-Checkliste für Lovable-Apps](https://madsalt.tech/de/blog/lovable-app-security-checklist/).

Unsicher, welchen Key Ihre App ausliefert?

Ich schaue gern drauf und tausche mich aus. Ohne Verkaufsgespräch.

[Kontakt aufnehmen](https://madsalt.tech/de/#contact)
