En bref
« RLS Disabled in Public » (lint 0013_rls_disabled_in_public, niveau ERROR) signifie qu’une table d’un schéma exposé a la row level security désactivée alors que anon ou authenticated peut la lire avec select. Dans mon test local, la clé publique a lu les 3 lignes sur 3 d’une telle table et en a inséré une nouvelle avec 201 Created. Activez la RLS, ajoutez une politique par opération et vérifiez les droits, dans une seule migration.
J’ai construit un audit de sécurité Supabase gratuit, et sa première règle, « RLS désactivé sur des tables exposées », est le même constat que le Security Advisor de Supabase signale comme une erreur. C’est la faille la plus courante que je trouve dans les applications construites avec des outils d’IA ; voici donc ce qu’elle signifie et ce qu’elle permettait quand je l’ai reproduite.
Que signifie « RLS disabled in public » ?
Le Security Advisor exécute un lint appelé rls_disabled_in_public. Son SQL signale une table quand trois conditions sont vraies en même temps :
- C’est une table ordinaire dont la row level security est désactivée.
anonouauthenticatedaSELECTdessus.- Son schéma figure dans la liste Exposed schemas de la Data API, qui vaut
publicpar défaut.
La page du lint le classe ERROR et qualifie de « a critically unsafe configuration » le fait de permettre création, lecture, modification et suppression complètes sur Internet. Le « public » du nom est le schéma, mais le lint couvre tous les schémas exposés, c’est pourquoi un schéma en plus dans cette liste mérite aussi un coup d’œil ; j’en ai parlé dans Supabase exposed schemas.
Que peut faire la clé publique à une telle table ?
J’ai créé une table orders avec trois faux clients sur un stack Supabase local (CLI 2.109.1, Postgres 17.6, PostgREST 14.14), avec les droits que les projets existants donnent aux nouvelles tables, et la RLS désactivée. Puis j’ai appelé la Data API avec la publishable key, comme le fait un navigateur :
| Requête avec la publishable key | RLS désactivée | RLS activée, aucune politique |
|---|---|---|
GET /rest/v1/orders?select=* |
200, les 3 lignes avec noms et e-mails |
200, [] |
POST /rest/v1/orders avec une nouvelle ligne |
201 Created |
401, 42501 « new row violates row-level security policy » |
Quiconque ouvre votre application peut copier la publishable key depuis la page. Avec la RLS désactivée, cette clé donne un accès en lecture et en écriture à cette table.
Comment corriger sans casser l’application ?
Activer la RLS seule fait que la table ne renvoie plus rien à l’application, faute de politique. Cet écran vide est le moment où des gens, et des outils d’IA, ajoutent une politique using (true), qui rend chaque ligne à tout le monde. Pourquoi les updates et les deletes signalent alors un succès sans rien changer est expliqué dans Activer la RLS dans Supabase : ce que renvoie chaque étape. Écrivez les vraies politiques dans la même migration :
alter table public.orders enable row level security;
revoke all on table public.orders from anon, authenticated;
grant select, insert on table public.orders to authenticated;
create policy "Customers read their orders"
on public.orders for select
to authenticated
using ((select auth.uid()) = user_id);
create policy "Customers create their orders"
on public.orders for insert
to authenticated
with check ((select auth.uid()) = user_id);
Si une table doit être publique, comme une liste d’articles publiés, gardez quand même la RLS activée et écrivez une seule politique select pour anon, sans droits d’écriture. Si vous n’utilisez jamais la Data API et ne parlez à Postgres que depuis votre serveur, retirez plutôt public de Exposed schemas, comme l’ont suggéré les mainteneurs de Supabase dans le même ticket.
Pour que les nouvelles tables ne démarrent jamais sans RLS, le guide des event triggers de Supabase propose un trigger qui l’active sur chaque table créée dans public. Et à partir du 30 octobre 2026, les nouvelles tables n’ont plus de droits Data API par défaut : elles répondent 42501 tant que vous ne les accordez pas ; je l’ai traité dans Supabase 42501 permission denied.
Que ne prouve pas un résultat propre ?
Que la RLS soit activée ne dit rien sur la justesse des politiques. Dans le même test, une politique écrite using (true) a de nouveau donné les 3 lignes à la clé publique, et ce lint se tait dès que la RLS est activée. L’audit a une règle distincte pour cela, « Politiques qui autorisent toutes les lignes », et comment tester Supabase RLS montre comment prouver chaque politique avec de vrais utilisateurs. Des politiques pour démarrer, chacune exécutée avec de vrais utilisateurs via l’API, sont dans Supabase RLS policy : exemples testés via l’API.