Hoppa till innehållet

Supabase 30 oktober: vad som går sönder och hur du kollar

Visa som MarkdownÖppna i ClaudeÖppna i ChatGPTÖppna i Perplexity

Frågan kopieras också. Om chatten öppnas tom, klistra in den.

Kort sagt

Den 30 oktober 2026 slutar Supabase ge nya tabeller i public automatiska behörigheter (grants) för anon, authenticated och service_role i alla befintliga projekt. Tabeller du redan har fortsätter fungera. Varje tabell som skapas efter det svarar 42501 permission denied till supabase-js och till din secret key tills en migration ger den behörighet. Jag återskapade omställningen lokalt: nya tabeller, nya vyer och gamla tabeller som en migration tar bort och skapar på nytt misslyckas alla; befintliga tabeller, RPC-funktioner och serial-inserts fortsätter fungera. Kontrollera med två SQL-frågor och en grep nedan, och åtgärda med grant, RLS och policy i samma migration, aldrig med grant all on all tables.

Jag driver en gratis Supabase-säkerhetskontroll som läser behörigheterna på varje exponerad tabell, så jag ville se exakt vad den här ändringen gör innan folk börjar köra in i den. Jag tog en lokal Supabase-stack, gav den de gamla standardvärdena, genomförde omställningen på det sätt Supabase beskriver och skickade en förfrågan mot varje sorts objekt jag kunde komma på. Det här inlägget är vad som kom tillbaka och hur du kontrollerar ditt eget projekt före den 30:e.

Vad ändras den 30 oktober 2026?

Hittills har varje tabell som skapats i schemat public fått select, insert, update och delete för anon, authenticated och service_role genom Postgres default privileges. Därför gick en ny tabell att nå från webbläsaren i samma stund den fanns, skyddad av RLS eller inte. Supabase meddelande om breaking change tar bort de standardvärdena i tre steg:

Datum Vad som händer
28 april 2026 Nya projekt kan välja bort “Automatically expose new tables” när de skapas
30 maj 2026 Det nya beteendet blir standard för nya projekt, utrullat under några veckor
30 oktober 2026 Det nya beteendet tillämpas på alla befintliga projekt

I ditt projekt är omställningen två satser, samma som Supabase anger för den som vill gå över tidigare:

alter default privileges for role postgres in schema public
  revoke select, insert, update, delete on tables from anon, authenticated, service_role;

alter default privileges for role postgres in schema public
  revoke usage, select on sequences from anon, authenticated, service_role;

Default privileges gäller bara objekt som skapas senare. Behörigheter som redan finns rörs inte, och därför fortsätter dina nuvarande tabeller att fungera. Enligt meddelandet påverkas inte: andra scheman (auth, storage, realtime, dina egna), appar som pratar med Postgres över en direktanslutning (psql, en ORM, en server med connection string) och RLS i sig. Ändringen gäller Data API:et: REST, GraphQL och varje klientbibliotek ovanpå dem.

Vad går sönder och vad fortsätter fungera?

Min uppsättning: Supabase CLI 2.109.1, Postgres 17.6, PostgREST 14.14, den 26 oktober 2026. Jag satte auto_expose_new_tables = true i config.toml för att få de gamla standardvärdena, skapade en tabell med två rader, RLS på och en läspolicy, och körde sedan de två satserna ovan. Därefter skapade jag nya objekt och anropade vart och ett med den lokala publika nyckeln (anon) och secret key (service_role), en förfrågan vardera.

Vad som slutar svara efter omställningen 30 oktober. Lokal Supabase, objekt skapade efter revoken i changeloggen, publik nyckel om inget annat anges. Ny tabell med RLS och en policy: create table → policy, ingen grant → 42501, HTTP 401; Samma tabell med secret key: create table → policy, ingen grant → 42501, HTTP 403; Ny vy över en tabell som fortfarande fungerar: create view → 42501, HTTP 401, ingen hint; Gammal tabell borttagen och omskapad av en migration: drop + create table → behörigheter borta → 42501, HTTP 401.
Min reproduktion på en lokal Supabase-stack (CLI 2.109.1, Postgres 17.6, PostgREST 14.14), 26 oktober 2026.
Vad som fortsätter fungera efter omställningen 30 oktober. Samma lokala stack, samma revoke, publik nyckel. Tabell skapad före omställningen: befintlig tabell → behörigheter kvar → 2 rader, HTTP 200; Ny funktion anropad över RPC: create function → execute via PUBLIC → HTTP 200; Ny serial-tabell, bara select och insert givna: id serial → sekvens har UPDATE → insert, HTTP 201.
Min reproduktion på en lokal Supabase-stack (CLI 2.109.1, Postgres 17.6, PostgREST 14.14), 26 oktober 2026.
Objekt, skapat efter omställningen om inget annat anges Nyckel Resultat
Tabell skapad före omställningen publik HTTP 200, 2 rader
Ny tabell med RLS och en policy to anon, authenticated publik HTTP 401, 42501, hint GRANT SELECT ON public.new_orders TO anon;
Samma nya tabell secret HTTP 403, 42501, hint … TO service_role;
Ny vy (security_invoker) över den gamla tabellen publik HTTP 401, 42501, permission denied for view, hint null
Kopia gjord med create table … (like old_orders including all) publik HTTP 401, 42501
Den gamla tabellen efter drop table och nytt create table publik HTTP 401, 42501
Ny funktion public.ping() över /rest/v1/rpc publik HTTP 200
Ny tabell med id serial, bara select, insert givet till anon publik insert HTTP 201

Fem saker i tabellen är värda att veta före omställningen.

“Befintliga tabeller behåller sina behörigheter” gäller bara så länge tabellen finns kvar. En migration som tar bort och skapar om en tabell, en kopia med create table … (like …) eller en återställning från en dump ger en ny tabell, och en ny tabell får ingenting. Policyn kom tillbaka med mitt create policy, behörigheterna gjorde det inte. Allt i din pipeline som bygger om tabeller i stället för att ändra dem går sönder vid första körningen efter omställningen.

Secret key går sönder också. service_role hoppar över RLS men behöver ändå en behörighet. Så en Edge Function, ett cron-jobb eller en webhook-hanterare som skriver till en ny tabell misslyckas med 403, inte bara webbläsaren. Hinten nämner service_role, och så skiljer du dem åt.

Vyer ger ingen hint. För tabeller returnerar PostgREST exakt den GRANT du behöver. För min nya vy var hinten null och meddelandet löd permission denied for view v_old_orders. Ett AI-verktyg som åtgärdar 42501 utifrån hinten har inget att kopiera här; behörigheten är grant select on public.v_old_orders to authenticated;, och vyn bör behålla security_invoker = true så att tabellens RLS fortfarande gäller.

Funktioner ingår inte i den här ändringen. De två satserna rör tabeller och sekvenser. Min nya funktion förblev anropsbar av anon, authenticated och service_role, eftersom Postgres ger execute på varje ny funktion till PUBLIC och en revoke på schemanivå inte kan ta bort det, som Supabase guide om att säkra API:et förklarar. RPC-anrop fortsätter fungera efter 30 oktober; det betyder också att en ny security definer-funktion går att anropa med din publika nyckel i samma stund den finns.

serial-inserts fortsatte fungera utan behörighet på sekvensen. Många råd säger att ett serial-id behöver grant usage on sequence … to authenticated efter omställningen. I min körning gick insert igenom utan: revoken tar usage och select på nya sekvenser, men update finns kvar, och update räcker för nextval. Om du återkallar alla default privileges på sekvenser, som den fullständiga revoken i API-guiden gör, behöver du usage-behörigheten. En identitetskolumn (generated by default as identity) behöver ingenting i något av fallen.

En sak till som revoken lämnar kvar: den nya tabellen kom fortfarande med TRUNCATE, REFERENCES och TRIGGER för alla tre rollerna, och i Postgres 17 innehåller standardvärdena även MAINTAIN. Ingen RLS-policy gäller för TRUNCATE. Det tog jag upp i noten om 42501.

Var du möter det före 30 oktober

Omställningen i ditt hostade projekt sker den 30:e, men tre ställen beter sig redan som efteråt.

supabase db reset med en aktuell CLI. CLI v2.102.0 lade till [api] auto_expose_new_tables i config.toml. På 2.109.1, med nyckeln utelämnad, hade min nya stack redan de nya standardvärdena: tabeller fick bara MAINTAIN, REFERENCES, TRIGGER och TRUNCATE, sekvenser bara UPDATE. Sätter du den till true kommer de gamla behörigheterna tillbaka och api.auto_expose_new_tables is deprecated and will be removed on 2026-10-30 skrivs ut. Så om dina lokala tabeller fortfarande fungerar efter en reset, kolla den nyckeln först. Det är också det billigaste stället att testa: ta bort den, kör reset, kör din app.

Preview-brancher och projekt skapade sedan 30 maj. De spelar upp dina migrations med de nya standardvärdena. Varje tabell vars migration saknar grant är redan onåbar där. I GitHub-diskussionen rapporterar folk med ett projekt per kund precis detta: de projekt som körs är fina, varje ny deploy från samma migrations är trasig.

En baseline-migration som tar tillbaka det gamla standardvärdet. En kommentator i samma diskussion påpekar att en första migration gjord med supabase db pull kan innehålla alter default privileges … grant all on tables to anon, authenticated, service_role. Jag körde den satsen efter omställningen: nästa tabell jag skapade gick att nå igen, HTTP 200. Lokalt döljer det problemet. Tillämpad på ditt hostade projekt ångrar den tyst ändringen, och varje framtida tabell är öppen för den publika nyckeln igen, med eller utan RLS. Sök igenom dina migrations efter alter default privileges och läs varje träff.

Så kontrollerar du ditt projekt före 30 oktober

Fyra kontroller, från snabbaste till grundligaste. De två första körs i SQL Editor i det hostade projektet.

1. Har ditt projekt ställts om än?

Det här är frågan från Supabase API-säkerhetsguide. Den listar vad nya objekt som skapas av postgres i public kommer att få:

select
  case d.defaclobjtype
    when 'r' then 'tables'
    when 'S' then 'sequences'
    when 'f' then 'functions'
  end as object_type,
  a.grantee::regrole as role,
  string_agg(a.privilege_type, ', ' order by a.privilege_type) as privileges
from pg_default_acl d
cross join lateral aclexplode(d.defaclacl) a
where d.defaclrole = 'postgres'::regrole
  and d.defaclnamespace = 'public'::regnamespace
  and a.grantee in ('anon'::regrole, 'authenticated'::regrole, 'service_role'::regrole)
group by 1, 2
order by 1, 2;

Om raderna för tables innehåller SELECT, INSERT, UPDATE, DELETE ligger projektet kvar på det gamla standardvärdet och ställs om den 30:e. Om de bara visar MAINTAIN, REFERENCES, TRIGGER, TRUNCATE (eller inga rader) är nya tabeller redan stängda. Du ser det också i Dashboard under Data API-inställningarna, “Automatically expose new tables”.

2. Vilka tabeller har en policy men ingen behörighet?

En policy för en roll som saknar behörighet för det kommandot körs aldrig: förfrågan misslyckas före RLS. Den här frågan listar de paren. I mitt labb hittade den den nya tabellen och den omskapade gamla, och inget annat:

select p.schemaname || '.' || p.tablename as "table", r.role, p.cmd
from pg_policies p
cross join lateral unnest(case when 'public' = any(p.roles) then array['anon', 'authenticated']::name[] else p.roles end) as r(role)
join pg_class c on c.relname = p.tablename
join pg_namespace n on n.oid = c.relnamespace and n.nspname = p.schemaname
where p.schemaname = 'public'
  and r.role in ('anon', 'authenticated')
  and not has_table_privilege(r.role::text, c.oid,
        case p.cmd when 'ALL' then 'SELECT' else p.cmd end)
order by 1, 2, 3;

Kör den efter varje migration, i CI mot en ny db reset eller på staging. I ett friskt projekt returnerar den ingenting; efter den 30:e är varje rad en tabell som din app inte når. Den kontrollerar behörigheter på tabellnivå, så en tabell som öppnats enbart med kolumnbehörigheter (grant select (id, name) on …) dyker upp här även om de kolumnerna går att läsa.

3. Vilka migrations skapar en tabell utan behörighet?

Databasen visar bara tabeller som finns. En migration du inte har kört än syns bara i ditt repo. Den här grova grepen listar varje create table i supabase/migrations utan grant … on för samma namn:

for t in $(grep -hioE 'create table( if not exists)? +[a-z0-9_."]+' supabase/migrations/*.sql | awk '{print $NF}' | sort -u); do
  grep -qiF "on $t " supabase/migrations/*.sql || grep -qiF "on table $t " supabase/migrations/*.sql || echo "no grant: $t"
done

Det är textmatchning, inte SQL-parsning: en grant som listar flera tabeller i en sats, eller en tabell som nämns utan schema på ett ställe och med schema på ett annat, ger en falsk träff. Läs varje rad den skriver ut. Tabeller som bara serverkod når över en direktanslutning behöver ingen behörighet alls.

4. Spela upp allt med de nya standardvärdena

Ta bort auto_expose_new_tables ur config.toml, kör supabase db reset och kör din app eller dess tester mot det. Det är ditt projekt efter den 30:e, plus en ny kopia av varje tabell, vilket är det svårare fallet. Supabase listar också berörda tabeller i Security Advisor och markerar Data API-exponering i Table Editor.

Så åtgärdar du det utan att öppna varje tabell

Skriv behörigheten, RLS och policyerna i migrationen som skapar tabellen, och ge varje roll bara det appen använder:

create table public.invoices (
  id bigint generated by default as identity primary key,
  user_id uuid not null default auth.uid(),
  total numeric not null
);

revoke all on table public.invoices from anon, authenticated, service_role;
grant select, insert on table public.invoices to authenticated;
grant select, insert, update, delete on table public.invoices to service_role;

alter table public.invoices enable row level security;

create policy "Owners read their invoices"
on public.invoices for select
to authenticated
using ((select auth.uid()) = user_id);

create policy "Owners add their invoices"
on public.invoices for insert
to authenticated
with check ((select auth.uid()) = user_id);

Jag körde det här blocket på samma lokala stack: en inloggad testanvändare lade in en rad och läste tillbaka den (HTTP 201, sedan 200), den publika nyckeln utan session fick 42501, och kontroll 2 ovan listade inte längre tabellen. Den inledande revoke all rensar bort TRUNCATE, TRIGGER och REFERENCES som följer med en ny tabell, och ger samma resultat i ett projekt som inte har ställts om än. Ge anon behörighet bara på data som är avsedd för utloggade besökare, och service_role bara om serverkod använder secret key på den här tabellen. Hur behörigheter och policyer hänger ihop i en hel app går jag igenom i min säkerhetschecklista för Lovable-appar.

Vad du inte ska göra när det första 42501 dyker upp:

  • Kör inte grant all on all tables in schema public to anon, authenticated. Det återinför det gamla standardvärdet för alla tabeller på en gång, inklusive varje tabell där RLS aldrig aktiverades, och de blir läsbara för alla som har din publika nyckel. Noten om 42501 visar varför behörigheten är det första låset och RLS det andra.
  • Lägg inte tillbaka alter default privileges … grant. Det är en rollback av hela ändringen.
  • Stäng inte av RLS för att “testa” och lägg inte secret key i frontend. Secret key hoppar över RLS för alla som öppnar din bundle; skillnaden mellan nycklarna finns i anon key vs service role key.

Om ett AI-verktyg skriver dina migrations, lägg till en rad i dess instruktioner: “every new table in public gets explicit grants per role, enable row level security and policies in the same migration; never grant on all tables in schema public”. Hinten i felet lär det behörigheten, aldrig den RLS som hör ihop med den.

Frågor folk ställer om ändringen

Slutar mina befintliga tabeller fungera den 30 oktober? Nej. Default privileges gäller objekt som skapas senare, och i min körning svarade den gamla tabellen HTTP 200 efter omställningen. Undantaget är en tabell som dina migrations tar bort och skapar på nytt.

Behöver jag göra något om jag aldrig skapar tabeller? Inte den 30:e. Kolla nästa gång du, en kollega eller ett AI-verktyg lägger till en, och kolla varje pipeline som skapar projekt eller brancher från dina migrations.

Påverkar det Edge Functions? Ja, om de använder supabase-js med secret key på en ny tabell: service_role behöver också en behörighet. Funktioner som ansluter direkt till Postgres påverkas inte.

Påverkar det RPC-funktioner, Storage eller Auth? Inte i den här ändringen. Nya funktioner förblir anropsbara via PUBLIC, och storage och auth är inte schemat public.

Kan jag ställa om tidigare? Ja. De två satserna överst är omställningen; kör dem på staging först, sedan i produktion. Befintliga tabeller behåller sina behörigheter, så en app som körs märker ingenting, och nästa nya tabell visar direkt om dina migrations är redo.

Så ser kontrollen på det här

Kontrollen ansluter skrivskyddat och läser behörigheterna på varje tabell i dina exponerade scheman: vilka tabeller den publika nyckeln kan skriva till utan policy, vilka tabeller som har RLS av och vilka default privileges som fortfarande ger varje ny tabell TRUNCATE, REFERENCES eller TRIGGER. Den listar också varje policy vars roll saknar behörighet för det kommandot, de tabeller som kontroll 2 hittar, utom dem med RLS avstängt eller med kolumnbehörigheter. Den ser inte migrationsfiler du inte har kört, så kontroll 3 ovan är fortfarande din att köra. Om det är RLS du är osäker på går hur du testar Supabase RLS igenom det, och noten om exponerade scheman täcker andra scheman än public, som den här ändringen lämnar ifred.

© 2026 Denys Zaichenko. Originalartikel: https://madsalt.tech/sv/blog/supabase-october-30-grant-change/