Hopp til innhold

Supabase exposed schemas: hva listen åpner for

Supabase

Vis som MarkdownÅpne i ClaudeÅpne i ChatGPTÅpne i Perplexity

Spørsmålet kopieres også. Hvis chatten åpnes tom, lim det inn.

TL;DR

Listen Exposed schemas i Supabase bestemmer hvilke skjemaer Data API-et serverer til alle som har den offentlige nøkkelen din. Standarden er public og graphql_public. Hver tabell, view og funksjon i et skjema på listen må ha sine egne tilganger og sin egen RLS, så hvert ekstra skjema er mer overflate å forsvare. Hold listen kort, og sjekk den først.

Jeg har bygget en gratis Supabase-sikkerhetssjekk, og listen Exposed schemas er en av de første tingene den leser. Når noen spør hvor trygt et Supabase-prosjekt er, er det her jeg begynner.

Hva betyr “exposed schemas” i Supabase Data API?

Supabase serverer databasen din over REST med PostgREST. PostgREST svarer bare for skjemaene i db_schema-listen sin, og den redigerer du i Dashboard under Project Settings → Data API → Exposed schemas. I prosjektkonfigurasjonen jeg så på, var verdien public,graphql_public, og Supabases veiledning om custom schemas sier at public er eksponert som standard. En forespørsel om et skjema utenfor listen blir avvist, og PostgREST tillater aldri pg_catalog eller information_schema i den.

Hvorfor spiller listen noen rolle?

Alt i et eksponert skjema kan nås med den offentlige nøkkelen: tabeller, views og funksjoner. Supabases RLS-guide er tydelig på det: en tabell i et eksponert skjema uten RLS kan leses og skrives av enhver rolle som har en tilgang til den. Et skjema som ikke står på listen, kan ikke nås gjennom API-et i det hele tatt.

Så et ekstra skjema er ikke en nøytral endring. Legg til storage eller vault i listen, og du har lagt interne tabeller innenfor rekkevidden til Data API-et. Legg til ditt eget skjema, og hver tabell i det krever samme omtanke som public.

Hva et ekstra exposed schema åpner for. Én anon-forespørsel før og etter at listen er trimmet. Før: et ekstra skjema er exposed: anon-spørring → Data API → ekstra skjema → tabell uten RLS kan leses; Etter: bare public og graphql_public: anon-spørring → Data API → bare standardskjemaer → RLS på alle tabeller.
Fra reglene i Supabase-sjekken og Supabases Data API-dokumentasjon, 22. oktober 2026.

Hvordan vurderer sjekken ekstra skjemaer?

Sjekken heter extra_exposed_schemas. Alt unntatt public og graphql_public regnes som ekstra, og deretter gjelder:

  • Et internt Supabase-skjema på listen (auth, storage, realtime, vault, extensions og lignende) er en feil med høy alvorlighet.
  • Bare egne skjemaer, for eksempel api, gir en advarsel med middels alvorlighet.
  • Ingen ekstra skjemaer gir bestått.

Den samme listen styrer andre sjekker. Tabeller med RLS slått av, skrivetilganger for anon, policyer som alltid er sanne, views uten security_invoker og SECURITY DEFINER-funksjoner som anon kan kalle, blir bare rapportert for eksponerte skjemaer, fordi det er der den offentlige nøkkelen når dem.

Hvordan bruker du et eget skjema trygt?

Et eget skjema er et legitimt mønster: Supabases guide Securing your API beskriver et dedikert skjema som api som en måte å gjøre den eksponerte flaten lettere å identifisere og gjennomgå, mens interne tabeller blir værende i skjemaer som ikke er eksponert. To steg får det til å fungere, og veiledningen om custom schemas beskriver begge: legg skjemaet til i Exposed schemas, og gi deretter usage på det til anon, authenticated og service_role, pluss tilganger på objektene i det.

Eksempelet i veiledningen gir ALL på hver tabell. Den linjen ville jeg ikke kopiert som den står. Guiden Securing your API sier at hver rolle bare skal få det minste den trenger, og at du skal aktivere RLS på hver tabell du eksponerer. Tilganger avgjør om en rolle i det hele tatt kan røre en tabell, policyer avgjør hvilke rader.

En separat endring: Supabase slutter å gi Data API-et automatisk tilgang til nye public-tabeller. Det ble standard for nye prosjekter fra 30. mai 2026 og blir innført for eksisterende prosjekter 30. oktober 2026, og eksisterende tabeller beholder tilgangene sine. Det er tilgangslaget. Det endrer ikke hvilke skjemaer som står på listen.

Hvordan sjekker du hvor trygt ditt eget Supabase-prosjekt er?

Åpne Project Settings → Data API, og les Exposed schemas. Hvis det står mer enn public og graphql_public, spør hva hvert ekstra skjema brukes til.

List deretter tabellene i disse skjemaene som har RLS slått av, og om anon allerede kan lese dem:

select n.nspname as schema,
       c.relname as "table",
       has_table_privilege('anon', c.oid, 'select') as anon_can_select
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where n.nspname in ('public', 'api')  -- your Exposed schemas
  and c.relkind in ('r', 'p')
  and not c.relrowsecurity
order by 1, 2;

Jeg kjørte den på en midlertidig Postgres 17 med et api-skjema med én tabell med RLS og én uten, pluss en public-tabell uten RLS. Den returnerte bare de to uten:

 schema | table  | anon_can_select
--------+--------+-----------------
 api    | orders | t
 public | logs   | t

Hver rad der anon_can_select er sann, er en tabell som alle med den offentlige nøkkelen din kan lese, helt til du aktiverer RLS eller trekker tilbake tilgangen. Spørringen dekker bare tabeller. Views og funksjoner må sjekkes hver for seg, og det går sikkerhetsjekklisten min for Lovable-apper gjennom, mens hvordan jeg tester Supabase RLS viser hvordan du beviser at policyene virker.

© 2026 Denys Zaichenko. Opprinnelig artikkel: https://madsalt.tech/no/notes/supabase-exposed-schemas/