Le scan est vert. Le client A peut-il lire la facture du client B ?
Le contrôle automatique d’une plateforme lit la configuration et vérifie que des règles d’accès existent. Il ne sait pas qui doit voir quelle facture. Ce test-là se fait avec deux comptes, une requête modifiée et une règle écrite en une phrase.

La plateforme affiche un contrôle de sécurité réussi. L’application est en production, des clients paient, leurs factures se téléchargent. Une question reste pourtant hors du tableau vert : si le client B remplace, dans sa requête, l’identifiant de sa facture par celui d’une facture du client A, que renvoie le serveur ?
Ce n’est pas une affaire d’outil. C’est une règle métier, « un client ne voit que ses propres factures », que personne n’a écrite ailleurs que dans sa tête. Voici pourquoi le contrôle automatique ne peut pas la deviner, où elle casse dans une application construite sur Supabase, et comment la vérifier avec deux comptes de test.
Prenons Lovable, dont la documentation est précise. Son analyse rapide « déroule un ensemble fixe de contrôles en quelques secondes » et se lance à chaque publication : tables sans sécurité au niveau des lignes, règles d’accès qui laissent passer tout le monde, dépendances npm vulnérables, serveurs MCP ouverts sans authentification[1]. Une analyse approfondie relit le code de l’application, permissions comprises ; elle ne se lance pas d’elle-même[1]. La page prévient enfin que ces outils « ne peuvent pas garantir une sécurité complète »[1].
Ce contrôle a progressé. En mars 2025, le chercheur Matt Palmer avait montré que des sites générés par Lovable laissaient lire leurs tables sans authentification. Il relevait que le scanner livré ensuite avec Lovable 2.0 vérifiait seulement qu’une politique RLS existait, « pas sa justesse ni son accord avec la logique de l’application »[2]. La faille porte l’identifiant CVE-2025-48757 et une note de gravité de 9,3 sur 10 ; Lovable la conteste, au motif que chaque client répond de la protection des données de son application[3].
Sur ce point, l’éditeur est cohérent. Le 21 octobre 2026, il a écrit ce qui reste à votre charge : « testez avec des comptes séparés et des rôles différents », puis cette question, presque celle de notre titre : un client peut-il lire les enregistrements d’un autre client[4] ? Son rapport SOC 2 évalue Lovable comme fournisseur et « ne constitue pas un audit de votre entreprise ou de votre application »[4]. Le tableau vert dit que la plateforme a relu sa liste. Il ne dit pas que votre règle est respectée.
Dans une application construite sur Supabase, le navigateur parle directement à la base, avec une clé inscrite dans le code de la page. C’est voulu. La documentation la dit « sûre à exposer » et précise qu’elle n’atteint que « ce que la sécurité au niveau des lignes autorise »[5]. La clé n’est donc pas le problème : la cacher ou la remplacer ne protège aucune facture.
Tout se joue donc dans le texte des politiques, et la même politique peut être juste ici, fausse là. « Tout utilisateur connecté lit toutes les factures » convient à un outil interne où une seule équipe partage ses données. Dans un logiciel vendu à plusieurs entreprises, c’est exactement la fuite du client A vers le client B. Rien dans la configuration ne dit laquelle des deux applications vous avez construite.
Un contrôle automatique repère sans peine la première colonne, et souvent la règle qui ouvre tout à tous. Entre « tout utilisateur connecté » et « le propriétaire de la ligne », il lui faudrait connaître votre intention. Or elle n’est écrite nulle part : elle vit dans la tête de l’équipe, dans un ticket, parfois dans la consigne donnée à l’agent qui a généré la base.
Ces failles ne font rien planter. Les pages s’affichent et les tests fonctionnels passent, parce qu’ils sont presque toujours écrits avec un seul compte. Voici quatre formes à connaître.
- La règle qui vérifie la connexion, pas le propriétaire. La politique exige un utilisateur connecté, ou un rôle, sans comparer la ligne à son compte. Dans un banc d’essai de l’éditeur Tenzai, quinze applications construites par cinq agents de code ne comportaient aucune injection SQL ni faille XSS exploitable, mais l’autorisation y était « très mal » appliquée : dans l’une, tout utilisateur doté du rôle « vendeur » pouvait consulter n’importe quelle commande[7].
- La politique ouverte. Une règle
using (true)accordée au rôle anonyme donne à chaque visiteur la lecture de toutes les lignes que ses droits atteignent ; Supabase la réserve aux données faites pour être publiques[6]. - La vue qui contourne. Les vues ignorent la RLS par défaut, parce qu’elles sont créées avec l’utilisateur
postgres: posée sur une table protégée, une vue rend toutes les lignes que ses politiques retenaient[6]. Sur PostgreSQL 15 et plus, l’optionsecurity_invoker = truela soumet aux politiques[6]. - La fonction serveur qui utilise la clé secrète. Appelée avec cette clé, une fonction côté serveur passe outre toutes les politiques[5]. Le contrôle d’appartenance doit alors être écrit dans son code, et testé comme tel.
Rien de tout cela n’est propre à l’IA. L’OWASP place le contrôle d’accès défaillant en tête de son Top 10 2025, avec cet exemple : consulter ou modifier le compte de quelqu’un d’autre en fournissant son identifiant[8]. Le même test vaut donc pour une API écrite à la main, hors de Supabase. Les agents écrivent vite un code qui marche ; la règle d’appartenance, elle, doit leur être donnée.
Chiffre clé
100 %
Supabase a changé un réglage par défaut le 30 octobre 2026 pour tous les projets existants : une table nouvellement créée dans le schéma public n’est plus exposée d’office à l’API, il faut l’ouvrir par une commande grant[9]. Les tables existantes gardent leurs droits, et le comportement de la RLS ne change pas[9].
Le changement ferme une porte, mais il fait apparaître une erreur. L’application reçoit le code 42501, « permission refusée », avec une indication qui donne la commande à passer, par exemple GRANT SELECT ON public.your_table TO anon;[9]. Supabase l’assume : l’indication est conçue pour qu’un agent se corrige seul[9]. Si la RLS est désactivée, ou si une politique autorise trop de lignes, l’agent qui suit cette indication rouvre ce que le changement voulait fermer, y compris aux visiteurs non connectés quand la commande vise le rôle anonyme. Avec la RLS activée et sans politique applicable, le droit SQL seul ne rend aucune ligne lisible.
Supabase donne la parade : écrire les grant dans la même migration que l’activation de la RLS et les politiques, et mettre à jour les consignes de l’outil d’IA qui crée les tables[9]. Une ligne dans le fichier de consignes de l’agent pose la règle : aucun grant sans politique écrite et testée.
Ces politiques peuvent aussi borner vos agents. Depuis le 22 octobre, Supabase propose de donner à une application son propre serveur MCP, le protocole par lequel un assistant d’IA appelle des outils : « chaque appel d’outil s’exécute en tant qu’utilisateur connecté, si bien que la RLS que vous avez déjà écrite décide de ce que chaque agent atteint »[10]. Dans cette architecture, une politique juste borne aussi l’agent ; une politique fausse lui ouvre les mêmes lignes qu’au client B. Cette protection ne s’étend ni aux connexions qui contournent la RLS, avec une clé secrète par exemple, ni au serveur MCP de développement, qui agit avec les droits du développeur.
Le test qui répond à la question du titre ne demande ni outil ni expertise rare. Il demande une phrase et deux comptes.
- Écrire la règle. Une phrase par type de document : « un client ne voit que ses factures ; l’administrateur d’un client voit celles de son entreprise ; un compte désactivé ne voit plus rien ».
- Créer deux comptes de test, A et B, rattachés à deux entreprises différentes, avec pour chacun une facture, un devis et un fichier téléversé. Vérifier d’abord que chaque compte retrouve ses propres documents.
- Rejouer, connecté en B, les requêtes qui affichent ces trois documents, en remplaçant l’identifiant par celui de A, dans l’adresse ou depuis les outils de développement du navigateur.
- Comparer la réponse au refus attendu : liste vide, ou réponse 403 ou 404, selon le contrat de l’API. Une erreur serveur, une requête invalide ou un résultat vide pour les deux comptes ne prouvent rien.
- Si la donnée revient, écrire un test automatique qui échoue avant de corriger, puis vérifier qu’il passe après. Conservé et exécuté à chaque changement, il signalera le retour de ce cas à la prochaine génération de code.
Supabase recommande d’écrire ces tests de politiques en SQL et de les lancer avec supabase test db. Sa documentation le dit sans détour : tant que la suite ne passe pas, « vous ne savez pas si les politiques font ce que vous vouliez »[6]. Pour commencer l’inventaire, deux requêtes dans l’éditeur SQL suffisent.
-- Tables publiques sans RLS
select tablename
from pg_tables
where schemaname = 'public'
and not rowsecurity;
-- Politiques ouvertes à tous
select tablename, policyname,
roles, cmd
from pg_policies
where schemaname = 'public'
and (qual = 'true'
or with_check = 'true');La seconde ne trouvera pas une règle qui vérifie seulement la connexion. Celle-là, seul le test des deux comptes la révèle.
Un droit se vérifie là où la donnée est servie : ni dans l’interface, ni dans la consigne donnée à l’agent, ni dans le tableau vert de la plateforme. Le contrôle automatique dit que la configuration a été relue. Le test des deux comptes dit si le client B voit la facture du client A. C’est la question que vos clients poseront.
Sources
Lovable Documentation — Security overview
docs.lovable.dev · non daté · consulté le · Documentation vivante, non datée : sections « Quick scan » et « Deep scan ». Citations traduites par nos soins.
Matt Palmer — Statement on CVE-2025-48757
mattpalmer.io · publié le · consulté le · Récit du chercheur : découverte le 20 mars 2025, éditeur prévenu le 21 mars.
NIST, National Vulnerability Database — CVE-2025-48757
nvd.nist.gov · publié le · consulté le · Lue par l’API de la NVD. Note CVSS 3.1 de 9,3 attribuée par le MITRE ; fiche marquée « disputed » par le fournisseur.
Lovable — Lovable’s compliance and your app: what’s covered, what’s your responsibility
lovable.dev · publié le · consulté le · Citations traduites par nos soins.
Supabase Docs — API keys
supabase.com · non daté · consulté le · Documentation vivante, non datée : clé publique (publishable, anciennement anon) et clé secrète (anciennement service_role).
Supabase Docs — Row Level Security
supabase.com · non daté · consulté le · Documentation vivante, non datée : politiques ouvertes, vues et security_invoker, tests de politiques.
Tenzai — Bad Vibes: Comparing the Secure Coding Capabilities of Popular Coding Agents
tenzai.com · publié le · consulté le · Banc d’essai conçu et noté par un éditeur d’outils de test : 15 applications, 5 agents, essais de décembre 2025. Date affichée sur la page de l’article consultée ; l’index du blog indique le 13 janvier 2026.
OWASP Top 10:2025 — A01:2025 – Broken Access Control
top10.owasp.org · non daté · consulté le · Édition 2025 du Top 10, page non datée : section « Background » et tableau des scores (40 CWE rattachées).
Supabase — Breaking Change: Tables not exposed to Data and GraphQL API automatically
supabase.com · publié le · consulté le · Annonce publiée le 28 avril 2026 ; bascule des projets existants le 30 octobre 2026.
Supabase — Give your Supabase app its own MCP server
supabase.com · publié le · consulté le · Citation traduite par nos soins.

