Sicherheitsgrundlagen
Supabase "permission denied for table": der fehlende Grant
Ab 30. Oktober antwortet eine neue Supabase-Tabelle mit "permission denied for table", bis du Zugriff erteilst. Der Grant aus der E-Mail ist die halbe Lösung.

Kurz gesagt
- Ab dem 30. Oktober 2026 antwortet eine neue Tabelle in deinem Supabase-Projekt mit "permission denied for table", bis jemand Zugriff auf sie erteilt. Die Tabellen, die du schon hast, funktionieren genau so weiter wie heute.
- Ein Grant entscheidet, ob eine Anfrage eine Tabelle überhaupt erreicht. Welche Zeilen sie zurückbekommt, entscheidet weiterhin Row Level Security. Wer anon Zugriff auf eine Tabelle ohne Regeln gibt, macht jede Zeile für jeden lesbar.
- Die Änderung schließt nichts, was schon offen ist. Prüf heute, was ein Fremder lesen kann, und danach wieder nach jeder neuen Tabelle.
Wenn deine App auf Supabase läuft, hast du wahrscheinlich eine E-Mail zum 30. Oktober bekommen. Darin steht, dass sich für deine bestehenden Tabellen
nichts ändert, und dann bekommst du drei SQL-Statements in die Hand gedrückt.
Oder es ist schon November: Du hast Lovable, Bolt oder Cursor um eine neue
Funktion gebeten, der neue Bildschirm bleibt leer, und irgendwo in der Konsole
steht eine Meldung mit permission denied for table. Beides ist dieselbe
Supabase-Änderung, nur von zwei Seiten des Datums aus gesehen.
Hier ist der Teil, den die E-Mail weglässt: Das SQL, das sie dir zeigt, ist nur die halbe Lösung. Führ diese Hälfte allein aus, auf der falschen Tabelle, und deine App läuft wieder, während die neue Tabelle ihre Zeilen jedem gibt, der danach fragt.
Was bedeutet "permission denied for table" in Supabase?
Es bedeutet, dass die Art von Besucher, die die Anfrage stellt, überhaupt keinen Zugriff auf diese Tabelle bekommen hat. Die Datenbank hat also abgelehnt, bevor sie sich auch nur eine Zeile angesehen hat.
Supabase ordnet jede Anfrage einer Rolle zu, also der Art von Besucher, von
der sie kommt. anon ist jemand, der nicht angemeldet ist. authenticated ist
jemand, der angemeldet ist. service_role ist dein eigener Servercode mit dem
geheimen Schlüssel. Ein Grant ist die Anweisung, die einer dieser Rollen
Zugriff auf eine Tabelle in Postgres gibt, der Datenbank, auf der Supabase
läuft. Ohne Grant kein Zugriff, egal was du sonst geschrieben hast.
Fehlt der Grant, antwortet Supabase so, meist als 401 oder 403:
{
"code": "42501",
"message": "permission denied for table comments",
"hint": "Grant the required privileges to the current role with: GRANT SELECT ON public.comments TO anon;"
}
Der Hinweis ist der nützliche Teil. Er nennt die Rolle, die abgewiesen wurde, und genau das Statement, das sie hereinlassen würde.
Stell dir jede Tabelle als Raum vor. Der Grant ist die Tür, und für jede Rolle gibt es eine eigene Tür. Row Level Security, die Regeln pro Zeile, die du vielleicht schon kennst, entscheidet, welche Schubladen ein Besucher öffnen darf, wenn er drinnen ist. "Permission denied for table" heißt, dass jemand vor einer geschlossenen Tür steht. Bis zu deinen Regeln ist er nie gekommen.
Was ändert sich am 30. Oktober?
Neue Tabellen im public-Schema, dem Tabellenordner, den dein Builder benutzt,
solange ihm niemand etwas anderes sagt, kommen ab dann mit geschlossenen Türen
an.
Bisher hat Supabase bei jeder neuen Tabelle automatisch alle drei Türen
geöffnet: Lesen, Hinzufügen, Ändern und Löschen, für anon, authenticated und
service_role gleichermaßen. Eine Tabelle war von deiner App aus erreichbar,
sobald sie existierte, und deine Row-Level-Security-Regeln waren das Einzige
zwischen einem Fremden und ihren Zeilen. Das
Changelog
von Supabase nennt den Grund ohne Umschweife: Agenten und KI-Plattformen legen
heute Tabellen an, ohne dass jemand die Änderung prüft, und die automatischen
Grants haben Tabellen offengelegt, die "a developer forgot to protect", die also
jemand zu schützen vergessen hatte.
| Datum | Was passiert ist oder passiert |
|---|---|
| 28. April 2026 | Neue Projekte konnten die automatischen Grants beim Anlegen abwählen. |
| 30. Mai 2026 | Der Verzicht auf automatische Grants wurde schrittweise Standard für neue Projekte. |
| 30. Oktober 2026 | Auch bestehende Projekte bekommen sie nicht mehr. |
Wenn dein Projekt nach Ende Mai angelegt wurde, funktioniert es vielleicht schon so, denn Supabase hat den neuen Standard in den Wochen nach diesem Datum nach und nach für neue Projekte eingeführt.
Drei Details solltest du vor dem Stichtag kennen:
- Nur das
public-Schema. Storage und die Anmeldung haben ihre Tabellen in eigenen Schemas,storageundauth, und laut Supabase bleiben deren Grants und Voreinstellungen, wie sie sind. - Auch der geheime Schlüssel wird abgewiesen. Die automatischen Grants
galten auch für
service_role. Eine Edge Function (Servercode, den Supabase für dich ausführt), die deinen geheimen Schlüssel benutzt, bekommt deshalb bei einer neuen Tabelle denselben Fehler, bisservice_roleeinen eigenen Grant hat. - Eine gelöschte und neu angelegte Tabelle ist eine neue Tabelle. Grants gehören zur Tabelle selbst und verschwinden mit ihr, wenn sie gelöscht wird. Baut dein Builder eine Tabelle neu, um sie zu ändern, beginnt die neu gebaute mit geschlossener Tür.
Geht meine App am 30. Oktober kaputt?
Nicht an diesem Tag. Sie geht kaputt, wenn zum ersten Mal etwas eine neue Tabelle anlegt, ohne auch den Grant anzulegen.
Für die meisten, die das hier lesen, ist dieses Etwas ihr Builder. Du bittest um
einen Kommentarbereich. Der Builder schreibt eine Migration, also die Datei mit
Datenbankänderungen, die er für dich ausführt, und die Migration legt eine
Tabelle comments an. Schreibt er die Grants gleich mit, siehst du diesen
Fehler nie. Tut er es nicht, zeigt der Kommentarbereich nichts an, oder das
Speichern eines Kommentars scheitert, oder eine rote Meldung erscheint, je
nachdem, wie deine App mit Fehlern umgeht. Jeder Bildschirm, den du schon
hattest, läuft weiter.
Supabase veröffentlicht einen Agent Skill für KI-Coding-Tools, der den Grant-Schritt enthält. Ob dein Builder ihn benutzt, entscheidet dein Builder. Geh also sicherheitshalber davon aus, dass die nächste Tabelle, die er anlegt, mit geschlossener Tür ankommen kann.
Kann ich den GRANT aus der Fehlermeldung gefahrlos ausführen?
Erst wenn für die Tabelle Row Level Security eingeschaltet ist und eine Regel für sie existiert. Der Grant entscheidet, wer durch die Tür kommt. Welche Schubladen jemand öffnet, entscheidet er nicht.
Der Schlüssel, mit dem deine App ihre Anfragen an Supabase stellt, steckt in
deiner App. Ein Grant an anon heißt also, dass jeder Besucher, angemeldet oder
nicht, diese Tabelle jetzt nach Zeilen fragen darf. Mit einer Regel bekommt er
die Zeilen, die die Regel erlaubt. Mit ausgeschalteter Row Level Security
bekommt er jede Zeile der Tabelle, und an deiner App sieht nichts anders aus.
Die E-Mail zeigt drei Grants und hört auf. Das Changelog von Supabase zeigt drei Schritte und sagt, man solle "treat these three steps as a unit", sie also als Einheit behandeln:
-- 1. wer die Tabelle erreichen darf
grant select on public.orders to authenticated;
grant select, insert, update, delete on public.orders to service_role;
-- 2. die Regeln pro Zeile einschalten
alter table public.orders enable row level security;
-- 3. die Regel selbst
create policy "Customers read their own orders"
on public.orders
for select
to authenticated
using (auth.uid() = user_id);
In diesem Beispiel gibt es keine Zeile für anon, und das ist Absicht.
Niemand, der abgemeldet ist, sollte eine Tabelle mit Bestellungen erreichen.
Die Tür für Fremde bleibt also zu, und angemeldete Kunden bekommen nur den
Lesezugriff, den ihr Bildschirm braucht. Die Regel grenzt das dann auf ihre
eigenen Zeilen ein. Supabase selbst rät,
jeder Rolle nur das Nötigste zu geben.
Ein Grant an anon gehört auf eine Tabelle, deren Zeilen für alle gedacht sind,
etwa die Kommentare unter einem öffentlichen Beitrag.
Wenn du sehen willst, auf welcher Seite dieses Bildes deine Tabellen stehen, stellt unser kostenloser Scan deiner Live-App die Frage, die ein Fremder stellen würde, zählt die Zeilen, die er bekäme, ohne eine davon abzurufen, und braucht dafür etwa 20 Sekunden ohne Konto: scanne deine App.
Warum die Row-Level-Security-Lösungen diesen Fehler nicht berühren
Weil zuerst der Grant geprüft wird. Eine Anfrage, die an der Tür abgewiesen wird, erreicht deine Regeln nie. Die Regeln zu ändern, ändert also nichts am Fehler.
Das ist wichtig, weil der Code geteilt ist. 42501 gibt Postgres auch zurück,
wenn Row Level Security ein Speichern ablehnt, wie bei
new row violates row-level security policy.
Ein Assistent, der sich nur am Code orientiert, greift womöglich zu den
Lösungen, die zu jenem Fehler gehören: Row Level Security ausschalten oder eine
Regel mit using (true) hinzufügen, die alle durchlässt. Keine von beiden lässt
diesen Fehler verschwinden. Beide bleiben zurück, wenn der Grant schließlich
kommt, und dann steht die Tür offen vor Schubladen ohne Schloss.
Die Worte in der Meldung unterscheiden die beiden, auch wenn die Nummer es nicht tut:
| Die Meldung lautet | Welches Schloss abgelehnt hat | Was es behebt |
|---|---|---|
permission denied for table | die Tür (der Grant) | ein Grant für die Rolle, die der Hinweis nennt |
new row violates row-level security policy | die Regeln | eine Policy, die diese Zeile erlaubt |
| kein Fehler, und die Liste ist leer | die Regeln | eine Lese-Policy für diese Rolle |
Was der 30. Oktober nicht behebt
Jede Tabelle, die du schon hast. Sie behält genau den Zugriff, den sie heute hat, auch eine Tabelle, die ein Fremder in diesem Moment lesen kann.
Die Änderung betrifft Tabellen, die es noch nicht gibt. Bisher kam jede neue Tabelle mit offenen Türen an. Eine App, die vor dem 30. Oktober gebaut wurde, kann also eine haben, bei der nie jemand die Schlösser angebracht hat: Row Level Security nie eingeschaltet, oder eingeschaltet unter einer Regel, die alle hereinlässt. Der 30. Oktober lässt diese Räume genau so, wie sie sind.
Drei Stellen zeigen dir, wo du stehst:
- Die Einstellungsseite der Data API, die in der E-Mail verlinkt ist. Im Dashboard liegt sie unter Integrations, dann Data API, und sie listet auf, welche deiner Tabellen überhaupt erreichbar sind.
- Der Security Advisor, der laut Supabase die Tabellen auflistet, die du vor der Änderung prüfen solltest.
- Der Blick von außen. Keine der beiden ersten Stellen sagt dir, was ein Fremder zurückbekommt. Dafür fragst du deine Live-App so, wie ein Fremder es tun würde, und genau das macht unser Scan.
Wie Reeve die Tabellen im Blick behält, die du hinzufügst
Nach dem 30. Oktober ist jede Tabelle, die dein Builder hinzufügt, eine neue Entscheidung darüber, wer durch die Tür kommt. Reeve prüft die Antwort von außen, und Monitor prüft sie immer wieder.
- Der kostenlose Scan fragt jede Tabelle, die deine App nennt, wie viele Zeilen ein Besucher ohne Login bekäme, liest die Zahl und hört dort auf, ohne eine Zeile abzurufen. Etwa 20 Sekunden, kein Konto: scanne deine App.
- Reeve Monitor führt jede Stunde alle neun Prüfungen für bis zu drei Apps aus und schickt dir an dem Tag eine E-Mail, an dem sich deine Note verschlechtert. Ein Deployment, das etwas geöffnet hat, wartet also nicht darauf, dass du nachsehen kommst.
- Care führt dieselben Prüfungen aus und bewahrt eine verschlüsselte Kopie deiner Supabase-Datenbank außerhalb deines Supabase-Kontos auf. Baut die Lösung eines Assistenten eine Tabelle neu, gibt es eine Kopie, zu der du zurückkehren kannst. Wie die Kopie entsteht und zurückgespielt wird.
Was jeder Tarif umfasst, steht auf der Preisseite.
Was du vor dem 30. Oktober tun solltest
Was zu tun ist
- Lass die Tabellen, die du schon hast, in Ruhe, wenn du nur willst, dass deine App weiterläuft. Sie behalten ihre Grants.
- Bitte deinen Builder, bei jeder neuen Tabelle den Grant,
enable row level securityund eine Policy in dieselbe Migration zu schreiben, als eine einzige Änderung. - Wenn der Fehler auftaucht, lies, welche Rolle der Hinweis nennt.
anonheißt jeder Besucher deiner App. - Gib
anonauf einer Tabelle nichts, solange Row Level Security nicht an ist und keine Regel existiert. Tabellen mit Menschen oder Bestellungen brauchen meist überhaupt keinen Grant füranon. - Lehne jede Lösung ab, die Row Level Security ausschaltet oder
using (true)hinzufügt, um einen Berechtigungsfehler zu beseitigen. Keine von beiden berührt ihn. - Prüf, was ein Fremder aus den Tabellen lesen kann, die du schon hast. Der 30. Oktober lässt sie, wie sie sind.
Fang mit der Tabelle an, die ein Fremder am liebsten lesen würde, meist die mit Menschen darin, und scanne deine App, um zu sehen, was sie heute herausgibt.
FAQ
Hört meine Supabase-App am 30. Oktober auf zu funktionieren?
Nein. Jede Tabelle, die am 30. Oktober existiert, behält den Zugriff, den sie hat, und Supabase hat bestätigt, dass diese Grants nicht entzogen werden. Was sich ändert, ist die nächste Tabelle, die nach diesem Datum angelegt wird. Sie ist für deine App zunächst unerreichbar, bis jemand Zugriff auf sie erteilt. Das Erste, was kaputtgeht, ist also die erste neue Funktion, die eine neue Tabelle braucht.
Was bedeutet "permission denied for table" in Supabase?
Es bedeutet, dass die Art von Besucher, die die Anfrage stellt, überhaupt keinen Zugriff auf diese Tabelle bekommen hat. Deine Datenbank hat also abgelehnt, bevor sie sich auch nur eine Zeile angesehen hat. Die Meldung kommt von Postgres, der Datenbank, auf der Supabase läuft, mit dem Code 42501, und erreicht deine App meist als 401 oder 403. Supabase hängt einen Hinweis an, der genau das GRANT-Statement nennt, das diesen Besucher hereinlassen würde.
Kann ich das GRANT-Statement aus der Fehlermeldung gefahrlos ausführen?
Erst wenn für die Tabelle Row Level Security eingeschaltet ist und eine Regel für sie existiert. Ein Grant an anon erlaubt jedem Besucher deiner App, die Tabelle nach Zeilen zu fragen, denn der Schlüssel, mit dem diese Anfragen gestellt werden, steckt in deiner App. Mit einer Regel bekommen sie die Zeilen, die die Regel erlaubt. Ohne Regel und mit ausgeschalteter Row Level Security bekommen sie alle.
Betrifft die Änderung Storage, die Anmeldung oder meine Edge Functions?
Storage und die Anmeldung liegen in eigenen Schemas, storage und auth, und laut Supabase bleiben deren Grants und Voreinstellungen, wie sie sind. Bei Edge Functions ist es anders. Eine, die deinen geheimen Schlüssel benutzt, braucht für jede neue Tabelle trotzdem einen Grant, denn die wegfallenden Standard-Grants galten auch für service_role und nicht nur für die zwei Rollen, die deine Besucher benutzen.
Kann ich das alte Verhalten wieder einschalten?
Supabase dokumentiert einen Weg dafür, als Einstellung auf der Data-API-Seite im Dashboard oder als SQL, und rät davon ab. Ist es an, ist jede neue Tabelle für jeden Besucher erreichbar, sobald sie existiert, und Row Level Security ist das Einzige, was zwischen einem Fremden und ihren Zeilen steht. So hat jedes Projekt vor der Änderung funktioniert.