Aller au contenu

Supabase exposed schemas : ce que la liste ouvre

Supabase

Voir en MarkdownOuvrir dans ClaudeOuvrir dans ChatGPTOuvrir dans Perplexity

La question est aussi copiée. Si le chat reste vide, collez-la.

En bref

La liste Exposed schemas de Supabase décide quels schémas la Data API sert à toute personne qui détient votre clé publique. Par défaut, ce sont public et graphql_public. Chaque table, vue et fonction d’un schéma de cette liste doit avoir ses propres droits (grants) et sa RLS : chaque schéma ajouté est donc une surface de plus à défendre. Gardez la liste courte et vérifiez-la en premier.

J’ai construit un audit de sécurité Supabase gratuit, et la liste des exposed schemas fait partie des premières choses qu’il lit. Quand on me demande si un projet Supabase est bien sécurisé, c’est par ce réglage que je commence.

Que signifie exposer un schéma dans Supabase ?

Supabase sert votre base de données en REST avec PostgREST. PostgREST ne répond que pour les schémas de sa liste db_schema, que vous modifiez dans le Dashboard sous Project Settings → Data API → Exposed schemas. Sur la configuration de projet que j’ai regardée, la valeur était public,graphql_public, et le guide des schémas personnalisés de Supabase indique que public est exposé par défaut. Une requête vers un schéma hors de la liste est refusée, et PostgREST n’autorise jamais pg_catalog ni information_schema dedans.

Pourquoi la liste compte-t-elle pour la sécurité ?

Tout ce qui se trouve dans un schéma exposé est accessible avec la clé publique : tables, vues et fonctions. Le guide RLS de Supabase est sans détour : une table d’un schéma exposé sans RLS est lisible et modifiable par tout rôle qui a un droit dessus. Un schéma absent de la liste est tout simplement inaccessible par l’API.

Un schéma de plus n’est donc pas un changement neutre. Ajoutez storage ou vault à la liste et vous mettez des tables internes à portée de la Data API. Ajoutez votre propre schéma et chaque table qu’il contient demande le même soin que public.

Ce que ouvre un schéma exposé en plus. Une requête anon, avant et après avoir raccourci la liste. Avant : un schéma en plus est exposé: requête anon → Data API → schéma en plus → table sans RLS lisible; Après : seulement public et graphql_public: requête anon → Data API → schémas par défaut → RLS sur chaque table.
Issu des règles de l'audit de sécurité Supabase et de la documentation de la Data API de Supabase, 22 octobre 2026.

Comment l’audit note-t-il les schémas supplémentaires ?

La vérification s’appelle extra_exposed_schemas. Tout ce qui n’est pas public ni graphql_public compte comme supplémentaire, puis :

  • Un schéma interne de Supabase dans la liste (auth, storage, realtime, vault, extensions et similaires) est un problème de gravité élevée.
  • Des schémas personnalisés seulement, par exemple api, donnent un avertissement de gravité moyenne.
  • Aucun schéma supplémentaire : la vérification est réussie.

La même liste pilote d’autres vérifications. Les tables sans RLS, les droits d’écriture pour anon, les politiques toujours vraies, les vues sans security_invoker et les fonctions SECURITY DEFINER que anon peut appeler ne sont signalés que pour les schémas exposés, car c’est là que la clé publique les atteint.

Comment utiliser un schéma personnalisé en sécurité ?

Utiliser un schéma personnalisé est une pratique légitime : le guide Securing your API de Supabase décrit un schéma dédié comme api comme un moyen de rendre la surface exposée plus facile à repérer et à auditer, les tables internes restant dans des schémas non exposés. Deux étapes le font fonctionner, et le guide des schémas personnalisés donne les deux : ajouter le schéma à Exposed schemas, puis accorder usage dessus à anon, authenticated et service_role, plus des privilèges sur ses objets.

L’exemple du guide accorde ALL sur chaque table. Je ne recopierais pas cette ligne telle quelle. Le guide Securing your API dit d’accorder à chaque rôle le minimum dont il a besoin, et d’activer la RLS sur chaque table que vous exposez. Les droits décident si un rôle peut toucher une table, les politiques décident quelles lignes.

Un changement distinct : Supabase cesse d’accorder automatiquement les nouvelles tables de public à la Data API. C’est devenu le comportement par défaut des nouveaux projets à partir du 30 mai 2026 et il sera appliqué aux projets existants le 30 octobre 2026 ; les tables existantes conservent leurs droits. C’est la couche des droits. Cela ne change pas les schémas présents dans la liste.

Comment vérifier votre propre projet Supabase ?

Ouvrez Project Settings → Data API et lisez Exposed schemas. Si la liste contient plus que public et graphql_public, demandez-vous à quoi sert chaque schéma supplémentaire.

Listez ensuite les tables de ces schémas dont la RLS est désactivée, et si anon peut déjà les lire :

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;

Je l’ai exécutée sur un Postgres 17 jetable avec un schéma api contenant une table avec RLS et une sans, plus une table public sans RLS. Elle n’a renvoyé que les deux tables sans RLS :

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

Chaque ligne où anon_can_select vaut true est une table que toute personne ayant votre clé publique peut lire, tant que vous n’activez pas la RLS ou ne retirez pas le droit. La requête ne couvre que les tables. Les vues et les fonctions demandent un examen à part, que détaille ma checklist de sécurité d’une application Lovable, et comment je teste la RLS de Supabase montre comment prouver que les politiques fonctionnent.

© 2026 Denys Zaichenko. Article original : https://madsalt.tech/fr/notes/supabase-exposed-schemas/