---
title: "Supabase exposed schemas: mitä lista avaa"
description: "Mitä Supabase exposed schemas tarkoittaa, miten tietoturvatarkistukseni arvioi ylimääräiset skeemat ja yksi SQL-kysely, joka löytää taulut ilman RLS:ää."
url: "https://madsalt.tech/fi/notes/supabase-exposed-schemas/"
author: "Denys Zaichenko"
language: "fi"
published: 2026-10-22
---

# Supabase exposed schemas: mitä lista avaa

TL;DR

Supabasen Exposed schemas -lista päättää, mitkä skeemat Data API tarjoaa jokaiselle, jolla on julkinen avaimesi. Oletuksena ne ovat `public` ja `graphql_public`. Jokaisella listalla olevan skeeman taululla, viewllä ja funktiolla on oltava omat oikeudet (grants) ja RLS, joten jokainen ylimääräinen skeema on lisää puolustettavaa pinta-alaa. Pidä lista lyhyenä ja tarkista se ensimmäisenä.

Rakensin ilmaisen [Supabase-tietoturvatarkistuksen](https://madsalt.tech/fi/tools/supabase-security-check/), ja Exposed schemas -lista on yksi ensimmäisistä asioista, jotka se lukee. Kun joku kysyy, kuinka turvallinen Supabase-projekti on, aloitan tästä asetuksesta.

## Mitä "exposed" tarkoittaa Supabasessa ja mitä Data API tekee?

Supabase tarjoaa tietokantasi REST-rajapintana PostgREST:n kautta. PostgREST vastaa vain `db_schema`-listansa skeemoille, jota muokkaat Dashboardissa kohdassa Project Settings → Data API → Exposed schemas. Tarkastelemassani projektin konfiguraatiossa arvo oli `public,graphql_public`, ja Supabasen [custom schemas -opas](https://supabase.com/docs/guides/api/using-custom-schemas) sanoo, että `public` on julkaistu oletuksena. Pyyntö listan ulkopuoliseen skeemaan hylätään, eikä [PostgREST](https://docs.postgrest.org/en/stable/references/api/schemas.html) salli listalla koskaan `pg_catalog`- tai `information_schema`-skeemaa.

## Miksi Exposed schemas -lista on tietoturvan kannalta tärkeä?

Kaikki julkaistun skeeman sisällä on tavoitettavissa julkisella avaimella: taulut, viewt ja funktiot. Supabasen [RLS-opas](https://supabase.com/docs/guides/database/postgres/row-level-security) on suorasanainen: julkaistun skeeman taulu ilman RLS:ää on luettavissa ja kirjoitettavissa jokaisella roolilla, jolla on siihen oikeus. Skeemaa, joka ei ole listalla, ei voi tavoittaa API:n kautta lainkaan.

Ylimääräinen skeema ei siis ole neutraali muutos. Lisää `storage` tai `vault` listalle, ja sisäiset taulut ovat Data API:n ulottuvilla. Lisää oma skeemasi, ja jokainen sen taulu vaatii saman huolellisuuden kuin `public`.

![Mitä ylimääräinen julkaistu skeema avaa. Yksi anon-pyyntö ennen listan karsimista ja sen jälkeen. Ennen: ylimääräinen skeema on julkaistu: anon-pyyntö → Data API → lisäskeema → RLS-ton taulu luettavissa; Jälkeen: vain public ja graphql_public: anon-pyyntö → Data API → vain oletusskeemat → RLS kaikissa tauluissa.](https://madsalt.tech/charts/fi/supabase-exposed-schemas.svg)

*Supabase-tietoturvatarkistuksen säännöistä ja Supabasen Data API -dokumentaatiosta, 22. lokakuuta 2026.*

## Miten tarkistus arvioi ylimääräiset skeemat?

Tarkistuksen nimi on `extra_exposed_schemas`. Ylimääräiseksi lasketaan kaikki paitsi `public` ja `graphql_public`, ja sitten:

- Supabasen sisäinen skeema listalla (`auth`, `storage`, `realtime`, `vault`, `extensions` ja vastaavat) on **fail, korkea vakavuus (high)**.
- Pelkät omat skeemat, esimerkiksi `api`, antavat **varoituksen (warning), keskitason vakavuus (medium)**.
- Ilman ylimääräisiä skeemoja tarkistus menee läpi.

Sama lista ohjaa myös muita tarkistuksia. Taulut ilman RLS:ää, anonin kirjoitusoikeudet, aina tosi -politiikat, ilman `security_invoker`-asetusta olevat viewt ja `SECURITY DEFINER` -funktiot, joita anon voi kutsua, raportoidaan vain julkaistuista skeemoista, koska julkinen avain yltää niihin juuri siellä.

## Miten oman skeeman voi ottaa turvallisesti käyttöön?

Oma skeema on aivan hyväksyttävä malli: Supabasen [Securing your API](https://supabase.com/docs/guides/api/securing-your-api) -opas kuvaa erillisen skeeman, kuten `api`, keinona tehdä julkaistusta pinta-alasta helpommin tunnistettava ja auditoitava, kun sisäiset taulut pysyvät skeemoissa, joita ei ole julkaistu. Kaksi vaihetta saa sen toimimaan, ja [custom schemas -opas](https://supabase.com/docs/guides/api/using-custom-schemas) antaa molemmat: lisää skeema Exposed schemas -listalle, anna sitten rooleille `anon`, `authenticated` ja `service_role` oikeus `usage` siihen sekä oikeudet sen objekteihin.

Oppaan esimerkki antaa `ALL` jokaiseen tauluun. En kopioisi sitä riviä sellaisenaan. Securing your API -opas sanoo antamaan jokaiselle roolille vähimmäisoikeudet, jotka se tarvitsee, ja ottamaan RLS:n käyttöön jokaisessa julkaisemassasi taulussa. Oikeudet (grants) ratkaisevat, saako rooli koskea tauluun, politiikat ratkaisevat, mihin riveihin.

Yksi erillinen muutos: Supabase [lopettaa uusien `public`-taulujen antamisen Data API:lle automaattisesti](https://supabase.com/changelog/45329-breaking-change-tables-not-exposed-to-data-and-graphql-api-automatically). Uusissa projekteissa siitä tuli oletus 30. toukokuuta 2026 alkaen ja olemassa oleviin projekteihin se otetaan käyttöön 30. lokakuuta 2026, ja olemassa olevat taulut säilyttävät oikeutensa. Se on oikeuksien (grants) kerros. Se ei muuta sitä, mitkä skeemat ovat listalla.

## Miten tarkistat oman projektisi?

Avaa Project Settings → Data API ja lue Exposed schemas. Jos siellä on enemmän kuin `public` ja `graphql_public`, kysy, mihin kutakin ylimääräistä skeemaa tarvitaan.

Listaa sitten näiden skeemojen taulut, joissa RLS on pois päältä, ja se, voiko `anon` jo lukea ne:

```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;
```

Ajoin sen väliaikaisella Postgres 17:llä, jossa oli `api`-skeema yhdellä RLS:llä suojatulla ja yhdellä ilman RLS:ää olevalla taululla, sekä `public`-taulu ilman RLS:ää. Se palautti vain nämä kaksi ilman RLS:ää:

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

Jokainen rivi, jossa `anon_can_select` on tosi, on taulu, jonka kuka tahansa julkisen avaimesi haltija voi lukea, kunnes otat RLS:n käyttöön tai peruutat oikeuden. Kysely kattaa vain taulut. Viewt ja funktiot vaativat oman tarkastelunsa, jonka käy läpi [Lovable-sovelluksen tietoturvatarkistuslistani](https://madsalt.tech/fi/blog/lovable-app-security-checklist/), ja [miten testaan Supabase RLS:ää](https://madsalt.tech/fi/blog/how-to-test-supabase-rls/) näyttää, miten todistat politiikkojen toimivan.
