Hoppa till innehållet

Så aktiverar du RLS i Supabase och vad du får tillbaka

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

Aktivera RLS i Supabase med en sats per tabell, alter table public.todos enable row level security;, eller med alternativet “Enable RLS” i dashboarden. Tabeller som skapas i SQL-editorn eller av en migrering får det inte som standard. Direkt efter att du aktiverat det blir tabellen tyst snarare än högljudd. I mitt lokala test fick den publika nyckeln och två inloggade användare 200 [] på select, update och delete, och bara insert misslyckades med 42501. Den hemliga nyckeln såg fortfarande alla 3 rader. En vanlig vy över tabellen gav fortfarande alla 3 rader till den publika nyckeln. Sedan den 30 oktober 2026 behöver en ny tabell dessutom ett grant innan något når den, så aktivera RLS och skriv policyer i samma migrering som granten.

Jag driver en gratis Supabase security checker, och “RLS disabled” är det fynd jag ser förklarat sämst. De flesta guider säger att efter att du aktiverat RLS “blir tabellen oåtkomlig”. Det stämmer för läsning och är missvisande för skrivning. Så jag byggde en tabell på en lokal Supabase-stack och skickade alla slags förfrågningar till den, som den publika nyckeln, som två inloggade användare och som den hemliga nyckeln, efter varje steg nedan.

Vad är RLS i Supabase?

RLS (row-level security) är en Postgres-funktion som filtrerar rader per förfrågan. Supabase gör varje förfrågan från supabase-js till en databasfråga som körs som en roll: anon för den publika nyckeln (anon, publishable), authenticated för en inloggad användare. Med RLS på kontrollerar Postgres dina policyer för varje rad och returnerar, ändrar eller tar bort bara de rader en policy tillåter. Med RLS av når varje roll med ett grant på tabellen alla rader.

Den hemliga nyckeln (service role) är annorlunda. Dess roll har BYPASSRLS, så RLS gäller aldrig för den. Därför hör den bara hemma på en server. Skillnaden mellan de två nycklarna finns i Supabase anon key vs service role key: vad var och en öppnar.

Hur aktiverar du RLS i Supabase?

Tre sätt, beroende på hur tabellen skapades:

  • När du skapar en tabell i Table Editor, låt “Enable Row Level Security (RLS)” vara ibockat. I Supabases dashboardkod är det markerat “Recommended”, och slår du av det visas en varning om att tabellen blir publikt läsbar och skrivbar.
  • För en befintlig tabell säger Supabases guide för att säkra API:t: gå till Database, sedan Policies, och välj “Enable RLS” på tabellen.
  • I SQL, i SQL-editorn eller en migrering:
alter table public.todos enable row level security;

Supabases guide är tydlig med att tabeller som skapas i dashboarden har RLS på som standard, och att tabeller som skapas i SQL-editorn eller med ett annat verktyg inte har det. Bygger du ditt schema med migreringar eller ett AI-verktyg, kontrollera varje tabell.

Vad händer direkt efter att du aktiverat RLS?

Inget ger fel utom insert. Jag skapade public.todos med en ägarkolumn (user_id uuid default auth.uid()), gav den grants till API-rollerna på samma sätt som äldre projekt och lade till tre rader: två ägda av användare A och en av användare B. Sedan aktiverade jag RLS utan policy:

Förfrågan Publik nyckel Användare A Användare B Hemlig nyckel
Select 200, 0 rader 200, 0 rader 200, 0 rader 200, 3 rader
Insert egen rad 401, fel 42501 403, fel 42501 403, fel 42501 201, rad infogad
Update en rad 200, 0 rader 200, 0 rader 200, 0 rader 200, 1 rad
Delete en rad 200, 0 rader 200, 0 rader 200, 0 rader 200, 1 rad

Insert-felet lyder new row violates row-level security policy. Update och delete svarar 200 med en tom lista, så en app som inte kontrollerar de returnerade raderna rapporterar “sparat” när inget sparades. Läs tillbaka dina skrivningar efter att du aktiverat RLS, eller be om ett antal med Prefer: count=exact.

Före RLS, med samma grants, kunde den publika nyckeln läsa alla 3 rader, infoga, och uppdatera eller ta bort vilken rad som helst. Användare A kunde ändra och ta bort användare B:s rad och lämna över sina egna rader till B.

Hur gör du tabellen användbar igen?

Skriv en policy per operation. Den vanliga uppsättningen för egna rader:

create policy "own select" on public.todos for select to authenticated
  using ((select auth.uid()) = user_id);
create policy "own insert" on public.todos for insert to authenticated
  with check ((select auth.uid()) = user_id);
create policy "own update" on public.todos for update to authenticated
  using ((select auth.uid()) = user_id) with check ((select auth.uid()) = user_id);
create policy "own delete" on public.todos for delete to authenticated
  using ((select auth.uid()) = user_id);

Med dem såg användare A sina 2 rader och användare B sin 1. Den publika nyckeln såg fortfarande 0. När A försökte infoga en rad som ägs av B, eller flytta sin egen rad till B, blev svaret 403, 42501. Det nekandet kommer från with check på update. När A försökte uppdatera eller ta bort B:s rad blev svaret 200, 0 rader. Fler mönster (publika profiler, team, MFA) finns i Supabase RLS policy-exempel, testade via API:t.

En detalj från den hemliga nyckeln: en rad den infogade fick user_id = null, eftersom auth.uid() inte har någon användare bakom den nyckeln. RLS hoppades över, men standardvärdet gjorde inte det som kolumnnamnet antyder.

Vad läste den publika nyckeln efter varje steg?

Rader den publika nyckeln läste, av 3. En Supabase-tabell med 3 rader, efter varje steg. Ny tabell, inget grant, RLS av (fel 42501): 0; Grant tillagt, RLS av: 3; RLS på, ingen policy: 0; RLS på, policyer för egna rader: 0; Vanlig vy över tabellen: 3; Vy med security_invoker: 0.
Figur 1. Lokal Supabase-stack (CLI 2.109.1, Postgres 17.6), 28 oktober 2026.

Två steg läcker allt: ett grant utan RLS och en vanlig vy över en tabell med korrekta policyer. De följande två avsnitten förklarar båda.

Behöver du fortfarande RLS efter grant-ändringen den 30 oktober?

Ja. Sedan den 30 oktober 2026 ger Supabase inte längre nya tabeller i public automatiska grants till API-rollerna, varken på nya eller befintliga projekt. Min lokala stack beter sig redan så. En nyskapad tabell med RLS av svarade 42501 till varje roll, även den hemliga nyckeln, så inget läckte. Detaljerna finns i Supabase 30 oktober: vad som går sönder och hur du kollar.

Men granten kommer tillbaka så fort appen behöver tabellen, och från då är RLS det enda som står mellan den publika nyckeln och varje rad. Så lägg allt i en migrering, i den här ordningen:

create table public.todos (...);
alter table public.todos enable row level security;
create policy "own select" on public.todos ...;
grant select, insert, update, delete on table public.todos to authenticated;

Ge grants bara till de roller som behöver tabellen. När jag drog in allt från anon ändrades den publika nyckelns select från 200 [] till 401, 42501. Granten är det första låset, RLS det andra.

Varför läcker en vy ändå rader?

Därför att en vy körs med sin ägares rättigheter, och i Supabase är det postgres, som kringgår RLS. Med policyerna för egna rader på plats på todos gav en vanlig create view public.todos_view as select * from public.todos alla 3 rader till den publika nyckeln och till användare B.

Skapad på nytt with (security_invoker = true) gav samma vy 0 rader till den publika nyckeln, 2 till A och 1 till B, precis som tabellen:

create view public.todos_view with (security_invoker = true) as
  select * from public.todos;

Supabases Advisor flaggar den vanliga sorten som security_definer_view; vad det betyder och hur du åtgärdar det finns i noten om Supabase security definer view.

Hur aktiverar du RLS på varje ny tabell automatiskt?

Med en event trigger. Supabases guide till event triggers ger en funktion rls_auto_enable() och en trigger ensure_rls som körs efter create table, create table as och select into i public. Jag installerade den som den är publicerad och fick:

  • En tabell som skapades efteråt med create table hade RLS på utan någon alter. Den publika nyckeln fick 200 [] på select och 401 på insert.
  • En tabell som skapades med create table as select hade också RLS på.
  • En tabell som skapades före triggern förblev av. Triggern gäller inte retroaktivt.

Utan triggern hade en andra tabell, skapad bredvid den skyddade, RLS av, och när den väl fått ett grant kunde den publika nyckeln läsa och skriva den fritt. Den täcker dessutom bara public; andra exponerade scheman behöver sin egen rad i funktionen.

Hjälper FORCE ROW LEVEL SECURITY?

Inte för de roller du oroar dig för. alter table ... force row level security får RLS att gälla även tabellens ägare. I Supabase har både postgres och service_role BYPASSRLS, så efter force räknade ägaren fortfarande 3 rader, den hemliga nyckeln såg fortfarande allt, och en vy som ägs av postgres läckte fortfarande. Det ändrade bara något för en ägarroll jag skapade utan BYPASSRLS: 2 rader före, 0 efter.

Hur kontrollerar du ditt eget projekt?

  • Lista i SQL-editorn tabellerna i public med RLS av:
select c.relname as table_name
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where n.nspname = 'public'
  and c.relkind in ('r', 'p')
  and not c.relrowsecurity
order by 1;
  • Advisor i dashboarden rapporterar samma sak som rls_disabled_in_public; vad det felet betyder finns i noten om RLS disabled in public.
  • Den kostnadsfria Supabase security check läser ditt projekt skrivskyddat och listar tabeller med RLS av som API:t kan nå, vyer som kringgår RLS och policyer som släpper in alla, med åtgärds-SQL för var och en.
  • En skanner kan inte veta vilka rader som tillhör vem. För att bevisa det, skicka förfrågningar som två användare, som ovan. Hela metoden för en app med roller finns i Testa Supabase RLS: 30 av 87 behörigheter gjorde inget.

Så testade jag

  • Supabase CLI 2.109.1 på en bärbar dator: Postgres 17.6, PostgREST 14.14, Auth 2.192.0. Två användare inloggade med lösenord, plus de lokala publishable och secret keys.
  • En tabell, public.todos, återställd till samma 3 rader före varje förfrågan. Varje steg utfördes som SQL, och varje förfrågan gick över REST-API:t, med statuskod och body antecknade.
  • Grants för steg 2 till 5 lades till för hand, för att motsvara ett projekt som skapats före den 30 oktober 2026.

Begränsningar. En lokal stack, påhittad data, 28 oktober 2026. Dashboard-stegen är citerade från Supabases dokumentation, inte klickade igenom. Tabeller som skapas av dashboardens egen roll kan få andra standardgrants. Det testade jag inte, inte heller Storage, Realtime eller GraphQL.

Osäker på om dina tabeller är låsta?

Jag tittar gärna på ett schema tillsammans med dig. Ingen säljpitch.

Kontakta mig

© 2026 Denys Zaichenko. Originalartikel: https://madsalt.tech/sv/blog/how-to-enable-rls-in-supabase/