Le Row Level Security (RLS) fonctionne comme un filtre automatique ajouté à chaque requête : avant de renvoyer une ligne, la base vérifie que la personne qui demande a le droit de la voir. Dans une app construite avec Lovable, Bolt ou un autre outil qui s'appuie sur Supabase, c'est souvent la seule chose qui sépare les données d'un client de celles d'un autre.
Pourquoi le RLS compte autant dans une app construite avec l'IA
Dans une app classique, le navigateur parle à un serveur, et le serveur parle à la base. Le serveur filtre. Avec Supabase, le navigateur interroge directement la base, avec une clé publique visible par n'importe quel visiteur. C'est voulu : la documentation Supabase décrit la clé publishable comme « sûre à exposer » dans une page web ou une app mobile.
La conséquence est simple. La protection ne vient pas de la clé, elle vient des règles écrites sur chaque table. Une table avec de bonnes règles reste fermée même si toute la planète connaît la clé. Une table sans règle adaptée s'ouvre à quiconque sait envoyer une requête.
Les outils IA produisent vite des tables et des écrans qui marchent. Ils écrivent aussi des règles, mais leur objectif implicite est que la fonctionnalité fonctionne du premier coup. Une règle trop large passe tous les tests visuels : l'écran s'affiche, les données apparaissent, personne ne remarque que l'utilisateur A pourrait aussi lire les données de l'utilisateur B. En mai 2025, une analyse de 1 645 apps publiées avec Lovable avait relevé 170 projets dont des données personnelles étaient accessibles de cette manière. Lovable propose désormais un scan rapide à chaque publication, qui signale notamment les tables sans contrôle d'accès par ligne. C'est un très bon filet, qui ne dispense pas de vérifier que chaque règle dit ce que tu crois.
Comment le RLS fonctionne, sans jargon inutile
Une règle RLS (une « policy ») répond à trois questions : pour quelle opération (lire,
créer, modifier, supprimer), pour quel rôle (visiteur anonyme ou utilisateur connecté),
et sous quelle condition. Par exemple : « un utilisateur connecté peut lire les lignes
de la table factures dont la colonne user_id est égale à son identifiant ».
Deux comportements surprennent souvent :
- RLS activé sans aucune règle : la table est fermée. Supabase précise qu'aucune donnée n'est accessible avec la clé publishable tant qu'aucune règle n'existe. L'app affiche des listes vides, ce qui pousse parfois à ajouter en urgence une règle « tout le monde peut tout lire »
- RLS désactivé : la table suit uniquement les droits généraux du rôle, ce qui revient souvent à l'ouvrir à tous les détenteurs de la clé publique
Pour les modifications, Supabase distingue deux clauses. USING décide quelles lignes
existantes peuvent être touchées. WITH CHECK décide à quoi la ligne doit ressembler
après l'opération. Sans WITH CHECK, un utilisateur pourrait modifier sa propre ligne
pour l'attribuer à quelqu'un d'autre.
Comment vérifier le RLS de ton app
Tu peux faire une première vérification sans écrire de code, depuis le tableau de bord Supabase :
- Liste toutes les tables du schéma
publicet note pour chacune si le RLS est activé. Supabase affiche un avertissement sur les tables exposées sans RLS - Lis les noms des règles. Une règle intitulée « Enable read access for all users » sur une table de profils ou de commandes mérite une question immédiate
- Cherche les conditions
true. Une règleusing (true)ouvre la lecture à tous les rôles visés. C'est correct pour un catalogue public, pas pour des données de clients - Vérifie la clé utilisée côté navigateur. Elle doit commencer par
sb_publishable_(ou être l'ancienne cléanon). Une clésb_secret_ouservice_roledans le code du front contourne toutes les règles - Teste avec deux comptes. Connecte-toi avec un compte A, note l'identifiant d'une donnée, puis essaie de la lire avec un compte B. C'est le test le plus parlant
Notre article sur Supabase et les accès détaille ce test pas à pas, et la checklist le replace parmi les autres contrôles avant l'arrivée de vrais utilisateurs.
Un exemple concret
Une plateforme de réservation construite en quelques semaines stocke les rendez-vous
dans une table bookings. La règle générée dit : « les utilisateurs connectés peuvent
lire les réservations ». Elle fonctionne parfaitement en démo, avec un seul compte. Le
jour où cent clients s'inscrivent, chacun d'eux peut lire l'agenda des quatre-vingt-dix-neuf
autres, avec les noms et les numéros de téléphone.
La correction prend quelques lignes : la règle devient « les utilisateurs connectés peuvent lire les réservations dont ils sont le client ou le prestataire », avec un index sur les colonnes concernées. Le vrai travail consiste à trouver toutes les tables dans ce cas, puis à vérifier que l'app fonctionne toujours après le resserrement.
Les erreurs les plus fréquentes
- La règle « tout ouvert » ajoutée pour débloquer un écran, puis oubliée
- La table ajoutée tard (logs, notifications, fichiers) qui n'a jamais reçu de règle
- La condition
auth.uid() = user_idseule : Supabase recommande d'ajouterauth.uid() IS NOT NULL, sinon la règle échoue silencieusement pour les visiteurs non connectés et peut produire des comportements inattendus - La clé secrète utilisée dans le navigateur pour faire passer une fonctionnalité qui butait sur une règle
- Les colonnes sans index : une règle qui filtre sur une colonne non indexée oblige la base à parcourir toute la table à chaque requête. L'app ralentit à mesure que les données grossissent
Ce qu'il faut retenir
Le RLS est un bon mécanisme, et il protège très bien une app dès que ses règles sont justes. Le point de vigilance se trouve rarement dans l'outil : il se trouve dans les règles écrites vite, au fil des itérations. Le Scan de vibebusters passe chaque table en revue, teste les accès croisés entre comptes et livre la liste des règles à corriger, classées par priorité.