● CWE-862 · OWASP A01:2021

Règles d'accès Supabase et Firebase (CWE-862) : comment l'absence de Row Level Security expose les données et comment corriger

Les applications Supabase et Firebase laissent le navigateur interroger directement la base avec une clé publique : entre un visiteur et chaque ligne, il n'y a que la Row Level Security ou les Security Rules. Une table créée en SQL sans enable row level security, ou une règle Firestore laissée à allow read, write: if true, est lisible et modifiable par n'importe qui. Comment les politiques USING et WITH CHECK limitent les lignes à l'utilisateur connecté, avec un exemple de migration PostgreSQL.

Explication en Langage Simple (ELI5)

Un immeuble de bureaux remet à chaque visiteur la même carte du hall, imprimée au dos de la brochure. Cela ne pose pas de problème tant que la porte de chaque étage vérifie qui vous êtes avant de s'ouvrir. Un étage a été aménagé à la hâte et sa porte n'a aucun lecteur : la carte du hall l'ouvre et n'importe qui peut entrer lire les dossiers. La clé anon de Supabase est la carte du hall : elle est faite pour être publique. La Row Level Security est le lecteur sur la porte de chaque étage. La correction consiste à installer un lecteur sur chaque porte et à lui indiquer précisément quels dossiers chacun peut voir.

Concepts Clés et Termes

Clé anon publique
La clé anon de Supabase et la configuration web de Firebase sont livrées dans le bundle de l'application, et n'importe qui peut les copier. Elles identifient le projet, pas l'utilisateur : ce ne sont pas des secrets et elles ne protègent pas les données à elles seules.
Row Level Security (RLS)
Une fonctionnalité de PostgreSQL qui filtre chaque requête à travers des politiques. Le Table Editor de Supabase l'active pour les nouvelles tables, mais les tables créées en SQL ou par migration démarrent sans RLS, et les droits par défaut laissent alors anon et authenticated lire et modifier toutes les lignes.
USING et WITH CHECK
USING détermine quelles lignes existantes un utilisateur peut voir, modifier ou supprimer ; WITH CHECK détermine quelles lignes nouvelles ou modifiées il peut écrire. Une politique n'ayant que USING sur insert ou update permet d'écrire des lignes pour une autre organisation.
Clé service_role
La clé service_role contourne entièrement la RLS. Elle n'a sa place que sur des serveurs et dans des edge functions, jamais dans un navigateur ou une application mobile.
Règles Firestore en mode test
Les projets démarrés en mode test reçoivent des règles qui autorisent toutes les lectures et écritures jusqu'à une date, et beaucoup finissent en allow read, write: if true. Les règles doivent comparer request.auth.uid au champ propriétaire du document.

Déroulement de l'Attaque Étape par Étape

Étape 1

L'attaquant ouvre l'application

L'URL Supabase et la clé anon se trouvent dans le bundle JavaScript ou le paquet de l'application mobile.

Étape 2

Il interroge directement la table

Il appelle l'endpoint REST de invoices avec la seule clé anon, sans passer par les écrans de l'application. Une requête vers un projet de test avec la clé anon et sans session utilisateur illustre le cas.

Étape 3

La base renvoie toutes les lignes

La RLS est désactivée et anon possède le droit select, donc PostgreSQL n'applique aucun filtre et renvoie les factures de toutes les organisations.

Étape 4

Des données fuient ou sont modifiées

Avec update et delete accordés aussi, l'attaquant peut modifier ou effacer des enregistrements. La CVE-2025-48757 a été attribuée en 2025 après que des chercheurs ont découvert qu'une RLS manquante exposait les données de plus de 170 applications générées par un créateur d'applications à base d'IA.

Code Source : Vulnérable vs Sécurisé

IMPLÉMENTATION VULNÉRABLE
-- migration.sql : la RLS n'est jamais activée sur cette table
create table public.invoices (
  id bigint generated always as identity primary key,
  org_id uuid not null references public.orgs (id),
  customer text not null,
  amount_cents bigint not null
);

-- la clé anon publique peut lire, modifier et supprimer toutes les lignes
grant select, insert, update, delete on public.invoices to anon, authenticated;
PATCH SÉCURISÉ ET ROBUSTE
-- migration.sql : RLS activée, anon révoqué, une politique par commande
create table public.invoices (
  id bigint generated always as identity primary key,
  org_id uuid not null references public.orgs (id),
  customer text not null,
  amount_cents bigint not null
);

-- une fois la RLS activée, sans politique il n'y a aucun accès
alter table public.invoices enable row level security;
revoke all on public.invoices from anon;

-- les utilisateurs ne voient que les factures de leurs organisations
create policy "members read their org's invoices"
  on public.invoices for select to authenticated
  using (org_id in (select org_id from public.memberships where user_id = (select auth.uid())));

-- les nouvelles lignes doivent appartenir à une organisation de l'utilisateur ; pas de politique update ni delete
create policy "members add invoices to their org"
  on public.invoices for insert to authenticated
  with check (org_id in (select org_id from public.memberships where user_id = (select auth.uid())));

Liste de Contrôle de Sécurité pour l'Ingénierie

Sources

← Parcourir tout l'annuaire sécurité Tous les guides de vulnérabilités →