---
title: "Supabase exposed schemas: hvad listen åbner for"
description: "Supabase exposed schemas forklaret: hvad indstillingen betyder, hvordan mit tjek vurderer ekstra schemas, og en SQL-forespørgsel, der finder tabeller uden RLS."
url: "https://madsalt.tech/da/notes/supabase-exposed-schemas/"
author: "Denys Zaichenko"
language: "da"
published: 2026-10-22
---

# Supabase exposed schemas: hvad listen åbner for

TL;DR

Listen Exposed schemas i Supabase afgør, hvilke schemas Data API'et leverer til enhver, der har din offentlige nøgle. Standarden er `public` og `graphql_public`. Hver tabel, view og funktion i et schema på listen skal have sine egne rettigheder og sin egen RLS, så hvert ekstra schema er mere overflade at forsvare. Hold listen kort, og tjek den først.

Jeg har bygget et gratis [Supabase-sikkerhedstjek](https://madsalt.tech/da/tools/supabase-security-check/), og listen Exposed schemas er en af de første ting, det læser. Når nogen spørger, hvor sikkert et Supabase-projekt er, er det her, jeg starter.

## Hvad betyder "exposed schemas" i Supabase Data API?

Supabase leverer din database over REST med PostgREST. PostgREST svarer kun for de schemas, der står i dens `db_schema`-liste, og den redigerer du i Dashboard under Project Settings → Data API → Exposed schemas. I den projektkonfiguration, jeg så på, var værdien `public,graphql_public`, og Supabases [guide til custom schemas](https://supabase.com/docs/guides/api/using-custom-schemas) siger, at `public` er eksponeret som standard. En anmodning om et schema uden for listen bliver afvist, og [PostgREST](https://docs.postgrest.org/en/stable/references/api/schemas.html) tillader aldrig `pg_catalog` eller `information_schema` i den.

## Hvorfor betyder listen noget?

Alt i et eksponeret schema kan nås med den offentlige nøgle: tabeller, views og funktioner. Supabases [RLS-guide](https://supabase.com/docs/guides/database/postgres/row-level-security) er tydelig: en tabel i et eksponeret schema uden RLS kan læses og skrives af enhver rolle med en rettighed på den. Et schema, der ikke står på listen, kan slet ikke nås gennem API'et.

Så et ekstra schema er ikke en neutral ændring. Tilføj `storage` eller `vault` til listen, og du har lagt interne tabeller inden for Data API'ets rækkevidde. Tilføj dit eget schema, og hver tabel i det kræver samme omhu som `public`.

![Hvad et ekstra exposed schema åbner for. Én anon-anmodning før og efter, at listen er beskåret. Før: et ekstra schema er exposed: anon-anmodning → Data API → ekstra schema → tabel uden RLS kan læses; Efter: kun public og graphql_public: anon-anmodning → Data API → kun standard-schemas → RLS på alle tabeller.](https://madsalt.tech/charts/da/supabase-exposed-schemas.svg)

*Fra Supabase-tjekkets regler og Supabases Data API-dokumentation, 22. oktober 2026.*

## Hvordan vurderer tjekket ekstra schemas?

Tjekket hedder `extra_exposed_schemas`. Alt undtagen `public` og `graphql_public` tæller som ekstra, og derefter gælder:

- Et internt Supabase-schema på listen (`auth`, `storage`, `realtime`, `vault`, `extensions` og lignende) er en **fejl med høj alvorlighed**.
- Kun egne schemas, for eksempel `api`, giver en **advarsel med middel alvorlighed**.
- Ingen ekstra schemas giver bestået.

Den samme liste styrer andre tjek. Tabeller med RLS slået fra, skriverettigheder til anon, policies der altid er sande, views uden `security_invoker` og `SECURITY DEFINER`-funktioner, som anon kan kalde, bliver kun rapporteret for eksponerede schemas, fordi det er dér, den offentlige nøgle når dem.

## Hvordan bruger du et eget schema sikkert?

Et eget schema er et legitimt mønster: Supabases guide [Securing your API](https://supabase.com/docs/guides/api/securing-your-api) beskriver et dedikeret schema som `api` som en måde at gøre den eksponerede overflade lettere at identificere og gennemgå, mens interne tabeller bliver i schemas, der ikke er eksponeret. To trin får det til at virke, og [guiden til custom schemas](https://supabase.com/docs/guides/api/using-custom-schemas) beskriver begge: tilføj schemaet til Exposed schemas, og giv derefter `usage` på det til `anon`, `authenticated` og `service_role`, plus rettigheder på dets objekter.

Guidens eksempel giver `ALL` på hver tabel. Den linje ville jeg ikke kopiere, som den står. Guiden Securing your API siger, at hver rolle kun skal have det mindste, den har brug for, og at du skal aktivere RLS på hver tabel, du eksponerer. Rettigheder afgør, om en rolle overhovedet kan røre en tabel, policies afgør hvilke rækker.

Én særskilt ændring: Supabase [holder op med automatisk at give Data API'et adgang til nye `public`-tabeller](https://supabase.com/changelog/45329-breaking-change-tables-not-exposed-to-data-and-graphql-api-automatically). Det blev standard for nye projekter fra 30. maj 2026 og bliver indført for eksisterende projekter den 30. oktober 2026, og eksisterende tabeller beholder deres rettigheder. Det er rettighedslaget. Det ændrer ikke, hvilke schemas der står på listen.

## Hvordan tjekker du, hvor sikkert dit eget Supabase-projekt er?

Åbn Project Settings → Data API, og læs Exposed schemas. Hvis der står mere end `public` og `graphql_public`, så spørg, hvad hvert ekstra schema skal bruges til.

List derefter de tabeller i de schemas, der har RLS slået fra, og om `anon` allerede kan læse dem:

```sql
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 kørte den på en midlertidig Postgres 17 med et `api`-schema med én tabel med RLS og én uden, plus en `public`-tabel uden RLS. Den returnerede kun de to uden:

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

Hver række, hvor `anon_can_select` er sand, er en tabel, som enhver med din offentlige nøgle kan læse, indtil du aktiverer RLS eller trækker rettigheden tilbage. Forespørgslen dækker kun tabeller. Views og funktioner kræver deres eget eftersyn, og det gennemgår min [sikkerhedstjekliste til Lovable-apps](https://madsalt.tech/da/blog/lovable-app-security-checklist/), mens [sådan tester jeg Supabase RLS](https://madsalt.tech/da/blog/how-to-test-supabase-rls/) viser, hvordan du beviser, at policies virker.
