---
title: "Supabase 30 oktober: vad som går sönder och hur du kollar"
description: "Den 30 oktober 2026 slutar Supabase öppna nya public-tabeller för API:et i befintliga projekt. Vad som går sönder, vad som funkar, 4 kontroller. Testat lokalt."
url: "https://madsalt.tech/sv/blog/supabase-october-30-grant-change/"
author: "Denys Zaichenko"
language: "sv"
published: 2026-10-26
---

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

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](https://madsalt.tech/sv/tools/supabase-security-check/) 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](https://supabase.com/changelog/45329-breaking-change-tables-not-exposed-to-data-and-graphql-api-automatically) 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:

```sql
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.](https://madsalt.tech/charts/sv/supabase-october-30-grant-change.svg)

*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.](https://madsalt.tech/charts/sv/supabase-october-30-grant-change-works.svg)

*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](https://supabase.com/docs/guides/api/securing-your-api) 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](https://madsalt.tech/sv/notes/supabase-42501-permission-denied/).

## 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](https://github.com/orgs/supabase/discussions/45329) 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å:

```sql
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:

```sql
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:

```bash
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:

```sql
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](https://madsalt.tech/sv/blog/lovable-app-security-checklist/).

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](https://madsalt.tech/sv/notes/supabase-42501-permission-denied/) 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](https://madsalt.tech/sv/blog/supabase-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](https://madsalt.tech/sv/blog/how-to-test-supabase-rls/) igenom det, och [noten om exponerade scheman](https://madsalt.tech/sv/notes/supabase-exposed-schemas/) täcker andra scheman än `public`, som den här ändringen lämnar ifred.
