Sécuriser une application Supabase avant sa mise en production
Le protocole d'audit pratique en 9 étapes pour vérifier l'étanchéité de votre base de données, la gestion des secrets et les autorisations avant de déployer.
Sur cette page (10 sections)▼
Créer une application avec Supabase et un outil de vibe coding (Cursor, Lovable, Bolt) permet de prototyper un produit complet en un temps record. Cependant, la mise à disposition d'une interface directe avec PostgreSQL via PostgREST implique que chaque table exposée devient une API publique potentielle.
Ce guide détaille une méthode structurée en 9 étapes concrètes pour auditer votre projet Supabase avant son ouverture aux utilisateurs réels.
1. Cartographier les données et l'ownership
La première démarche consiste à classifier la sensibilité de chaque table de votre schéma public :
- Données publiques : Articles de blog, catalogue de produits publics, configurations générales accessibles en lecture anonyme.
- Données privées liées à un compte : Profils utilisateurs, documents personnels, paniers d'achat, historiques de commande.
- Données sensibles ou administratives : Factures, abonnements Stripe, journaux d'audit, colonnes de rôles (
role,is_admin).
Pour chaque table contenant des données privées, identifiez clairement la colonne qui établit la propriété de la ressource (généralement user_id uuid references auth.users(id) ou workspace_id).
2. Vérifier l'activation et les politiques RLS
Pour chaque table de votre base de données :
- Vérifier l'activation effective : Assurez-vous que RLS est formellement activé. Si vous déclarez des politiques sur une table sans exécuter
ALTER TABLE public.nom_table ENABLE ROW LEVEL SECURITY;, PostgreSQL ignore les politiques et laisse la table ouverte. - Distinguer les opérations : Évitez les politiques génériques
FOR ALL. Définissez des politiques distinctes pourSELECT,INSERT,UPDATEetDELETE. - Contrôler la clause USING et WITH CHECK : Assurez-vous que l'écriture empêche l'usurpation d'identité en vérifiant systématiquement
WITH CHECK (auth.uid() = user_id).
Pour approfondir le fonctionnement exact de ces clauses et éviter les faux sentiments de sécurité, consultez notre Wiki sur le Row Level Security Supabase.
3. Vérifier la gestion des clés et l'étanchéité des secrets
La configuration des identifiants Supabase conditionne l'ensemble de votre sécurité :
- Clé publique
anon: Destinée au frontend (NEXT_PUBLIC_SUPABASE_ANON_KEY), elle est publique par conception. Sa sécurité dépend exclusivement de vos politiques RLS. - Clé privée
service_role: Cette clé utilise le rôle PostgreSQLservice_rolequi possède l'attributBYPASSRLS. Elle permet d'effectuer des tâches d'administration en contournant le filtrage des lignes. Elle ne doit être présente que dans vos variables d'environnement serveur protégées (SUPABASE_SERVICE_ROLE_KEY) et ne doit jamais être exposée dans un composant client. - Chaîne de connexion directe (Database URL) : Ne stockez jamais le mot de passe administrateur de votre base de données dans le code de votre application.
Pour comprendre comment inspecter votre bundle compilé et éviter les fuites de clés sensibles, consultez notre Wiki sur les secrets exposés côté navigateur.
4. Auditer l'authentification et les redirections
L'authentification gérée par Supabase Auth requiert plusieurs points d'attention :
- Validation des URLs de redirection (Redirect URLs) : Dans le dashboard Supabase (Authentication > URL Configuration), supprimez les jokers trop permissifs (comme
*) et ne conservez que vos domaines de production et de pré-production légitimes afin d'empêcher les attaques par vol de jeton d'authentification lors des réinitialisations de mot de passe ou des flux OAuth. - Énumération de comptes : Activez l'option d'obfuscation des erreurs d'authentification pour éviter qu'un tiers ne puisse tester l'existence d'adresses email enregistrées sur votre plateforme.
5. Contrôler les fonctions RPC et extensions PostgreSQL
Lorsque vous exposez des fonctions stockées (CREATE FUNCTION) appelables depuis le client via supabase.rpc() :
- Privilégier SECURITY INVOKER : Par défaut, concevez vos fonctions en
SECURITY INVOKERafin qu'elles s'exécutent avec les permissions et le contexte RLS de l'utilisateur qui effectue l'appel. - Sécuriser SECURITY DEFINER lorsque c'est indispensable : Si une fonction doit nécessairement s'exécuter avec les privilèges de son créateur (par exemple pour insérer dans une table d'audit non accessible à l'utilisateur), fixez explicitement un
search_pathsûr — idéalement vide (SET search_path = '') selon la recommandation officielle Supabase — et préfixez systématiquement tous les noms de tables et de types par leur schéma (public.documents). Validez également rigoureusement l'identité de l'appelant (auth.uid()) au sein de la fonction. - Permissions d'exécution : Révoquez l'accès public par défaut (
REVOKE EXECUTE ON FUNCTION ... FROM public;) et accordez-le uniquement aux rôles nécessaires (GRANT EXECUTE ON FUNCTION ... TO authenticated;).
6. Vérifier les opérations destructives (UPDATE / DELETE)
Une erreur fréquente dans les applications d'édition consiste à vérifier l'authentification sans vérifier la propriété de la ligne modifiée :
- Assurez-vous que chaque mutation exige une clause d'appartenance. Par exemple, une mise à jour d'un document doit vérifier que
auth.uid() = user_id. - Empêchez l'élévation de privilèges : si votre table de profils contient un champ
role, assurez-vous via un trigger ou une politique stricte qu'un utilisateur ne peut pas s'auto-attribuer le statut administrateur via une requête API directe.
7. Assainir les journaux et cibler les colonnes récupérées
Vérifiez les données retournées par vos requêtes et vos journaux d'application :
- Éviter
SELECT *sur les requêtes sensibles : Privilégiez la sélection explicite des seules colonnes nécessaires à l'écran. ÉvitezSELECT *lorsque cela risque de rapatrier ou d'exposer inutilement des champs privés, techniques ou des colonnes sensibles dans le payload JSON transmis au client. - Logs serveur : Assurez-vous que vos Route Handlers ou Server Actions n'enregistrent pas les jetons de session, les mots de passe ou les emails en clair dans les outils de suivi externe.
8. Tester avec plusieurs profils étanches
Avant de déclarer votre projet prêt pour la production, réalisez systématiquement le test des trois profils :
- Profil Non Connecté (Visiteur anonyme) : Tentez d'accéder aux endpoints et aux tables. Seules les données explicitement publiques doivent être lisibles.
- Profil Utilisateur A : Créez une ressource privée et notez son identifiant (
UUID). - Profil Utilisateur B : Dans une session de navigation privée distincte, tentez d'accéder directement à la ressource de l'utilisateur A en lecture, en modification et en suppression. La réponse doit être vide ou bloquée avec une erreur 404/403.
9. Checklist récapitulative avant mise en ligne
Utilisez cette liste de contrôle rapide pour valider chaque table avant le déploiement :
□ RLS est activé sur 100 % des tables du schéma public
□ Aucune table privée ne dispose d'une règle "FOR ALL USING (true)"
□ Les opérations INSERT valident "WITH CHECK (auth.uid() = user_id)"
□ La clé "service_role" est absente du code client et des variables NEXT_PUBLIC_
□ Les URLs de redirection Supabase Auth sont restreintes à votre domaine
□ Les fonctions sont en SECURITY INVOKER, ou SECURITY DEFINER avec search_path fixé
□ Le test croisé entre deux comptes utilisateurs distincts a été validé avec succès
Vérification continue avec GVO
Pour auditer votre application de façon automatique et reproductible, vous pouvez connecter votre référentiel de code à GVO :
- Ce que GVO analyse : GVO examine vos composants, vos Server Actions et vos schémas de base de données pour détecter l'absence démontrable de protection RLS, les politiques visiblement trop permissives, les fuites de secrets vers le navigateur et les risques de surcoûts d'API.
- Résultats et preuves : Chaque observation est classée avec précision (Confirmé, Probable, À vérifier) et accompagnée des extraits de code source concernés, sans jamais prétendre à une certification magique de conformité.
Pour comprendre la signification des constats générés lors d'un audit de votre projet, reportez-vous à la documentation sur la Compréhension d'un finding GVO.
À poursuivre
Vérifier ce point sur votre projet
GVO confronte le code et les configurations de votre application aux règles de sécurité réelles.