Faille IDOR : quand ton API renvoie les données des autres


Sommaire
- Une faille IDOR, c'est quoi exactement ?
- Pourquoi ton app codée avec l'IA y est particulièrement exposée ?
- À quoi ressemble une faille IDOR en pratique ?
- Quelles sont les deux formes d'IDOR ?
- Comment vérifier ton propre site ?
- Le prompt à coller dans ton agent pour corriger
- Les correctifs qui tiennent dans le temps
- Questions fréquentes
- Quelle est la différence entre IDOR et BOLA ?
- Est-ce qu'utiliser des UUID corrige une faille IDOR ?
- Comment savoir si mon site a une faille IDOR ?
- Un IDOR est-il une faille grave ?
- Où se classe l'IDOR dans l'OWASP Top 10 ?
- Sources
Une faille IDOR (Insecure Direct Object Reference, ou « référence directe non sécurisée à un objet ») survient quand ton application vérifie qu'un utilisateur est connecté, mais pas qu'il a le droit d'accéder à la ressource précise qu'il demande. Concrètement : il change un identifiant dans l'URL — /factures/124 au lieu de /factures/123 — et ton serveur lui renvoie la facture de quelqu'un d'autre. C'est une faille de contrôle d'accès, la plus fréquente sur les apps construites vite, et elle se corrige en quelques lignes.
Imagine ton SaaS codé avec Claude Code. Un client se connecte, ouvre sa facture et, par curiosité, remplace le numéro dans la barre d'adresse. Il tombe sur la facture d'un autre client : nom, adresse, montant. Il n'a rien cassé, juste changé un chiffre. C'est exactement une faille IDOR, et c'est aussi ce que ferait n'importe quel attaquant, en automatisé, sur tous les identifiants possibles.
Une faille IDOR, c'est quoi exactement ?
IDOR signifie Insecure Direct Object Reference. L'« objet », c'est une ressource : un profil, une facture, un projet, un fichier, une ligne en base de données. La « référence directe », c'est le fait que ton app y accède par un identifiant visible, souvent dans l'URL ou dans la requête : /api/utilisateurs/42, /factures/123, ?id=7.
La faille tient à une confusion entre deux notions que beaucoup de développeurs — et d'agents IA — mélangent :
- L'authentification : « Es-tu bien qui tu prétends être ? » Autrement dit, tu as un compte et tu es connecté.
- L'autorisation : « As-tu le droit d'accéder à cette ressource précise ? »
Une faille IDOR, c'est le cas où l'authentification est faite mais où l'autorisation est oubliée. Le serveur vérifie que l'utilisateur possède un jeton valide, puis il exécute la requête avec l'identifiant fourni, sans se demander si cet objet appartient à cet utilisateur.
Le résultat : n'importe quel utilisateur connecté — parfois même non connecté — peut lire, et souvent modifier, des données qui ne sont pas les siennes.
Pourquoi ton app codée avec l'IA y est particulièrement exposée ?
C'est le point important pour toi, vibecodeur. Une faille IDOR n'est pas un bug subtil : c'est souvent la sortie par défaut de l'agent quand tu lui demandes « fais-moi une page pour afficher la commande d'un client ».
L'agent génère une route qui fait ceci : récupère l'identifiant dans l'URL, interroge la base, renvoie le résultat. Il pense au chemin nominal — l'utilisateur tape son propre identifiant — et pas au cas où quelqu'un taperait celui du voisin. Il n'ajoute pas de contrôle d'appartenance si tu ne le demandes pas explicitement.
Trois situations typiques sur les apps générées :
- Une route API Next.js qui renvoie trop.
/api/commandes/[id]fait unselectsuridet renvoie l'objet entier — email, adresse, montant — à quiconque fournit unidvalide. - Supabase sans Row Level Security. La table est accessible via la clé anon et aucune policy ne restreint les lignes à leur propriétaire. C'est un IDOR à grande échelle : l'utilisateur peut lister les lignes des autres directement depuis l'API REST de Supabase. Si c'est ton cas, commence par activer et configurer la Row Level Security de Supabase.
- Des identifiants séquentiels prévisibles.
1, 2, 3…. Un attaquant n'a pas besoin de deviner : il énumère.
À quoi ressemble une faille IDOR en pratique ?
Prenons une petite app de gestion de projets. Ta cliente Alice possède le projet numéro 42. Quand elle ouvre /projets/42, ton serveur exécute :
SELECT * FROM projets WHERE id = 42
Puis il renvoie le résultat. Tant qu'Alice demande le 42, tout va bien. Le problème, c'est que rien dans cette requête ne dit « et où proprietaire = Alice ». Un autre utilisateur, Bob, n'a qu'à taper /projets/42 — ou envoyer la même requête API avec id=42 — pour recevoir le projet d'Alice.
Je ne te montre volontairement aucun code d'attaque : il n'y en a pas besoin. « Changer un chiffre dans l'URL » décrit tout le mécanisme. Ce qui compte, c'est ce que ton serveur fait de ce chiffre.
La version corrigée de la requête ressemble à ça :
SELECT * FROM projets WHERE id = 42 AND proprietaire = utilisateur_connecte
Le principe tient en une phrase : la condition d'appartenance est ajoutée côté serveur, à chaque requête. Le serveur ne fait jamais confiance à l'identifiant envoyé par le navigateur.

Quelles sont les deux formes d'IDOR ?
On distingue deux directions :
- IDOR horizontal : un utilisateur accède aux données d'un autre utilisateur de même niveau. Bob lit les factures d'Alice. C'est le cas le plus courant.
- IDOR vertical : un utilisateur accède à une fonction ou des données réservées à un niveau supérieur. Un client standard modifie
role=userenrole=admindans une requête, et le serveur l'enregistre sans vérifier.
Quand la faille concerne une API — une route JSON plutôt qu'une page — on l'appelle souvent BOLA (Broken Object Level Authorization). C'est le même problème avec un nom différent, utilisé notamment dans le Top 10 des API de l'OWASP.
Dans le Top 10 web de l'OWASP, l'IDOR est classé dans la catégorie A01:2021 — Broken Access Control (contrôle d'accès défaillant), qui occupe la première place des risques.
Comment vérifier ton propre site ?
Tu n'as pas besoin d'être pentester pour repérer les IDOR les plus évidents sur ta propre app. Voici une passe simple, réalisable en une heure :
- Liste tes routes et endpoints. Note chaque route qui prend un identifiant :
/api/[id],/factures/123,?id=, etc. - Pour chacune, pose la question : « Où est la vérification que cet objet appartient à l'utilisateur connecté ? » Si la réponse est « nulle part », tu tiens une faille IDOR.
- Vérifie Supabase. Ouvre le dashboard, va dans la table, et regarde si RLS est activé. Sans RLS, toute table accessible par la clé anon est lisible par tout le monde.
- Regarde ce que renvoient tes routes. Une route qui renvoie l'objet complet (
email,adresse,stripe_customer_id…) est plus dangereuse qu'une route qui renvoie juste les champs nécessaires. - Teste avec un second compte. Crée deux comptes, connecte-toi avec le premier, et essaie d'accéder à une ressource du second en changeant l'identifiant. Si ça passe, c'est confirmé.
Ces oublis ne sont pas propres à Next.js : les apps générées par Lovable, Bolt ou v0 les cumulent aussi, comme on l'a détaillé pour les failles de sécurité des apps Lovable.
Le principe de base : ta sécurité ne doit jamais reposer sur le fait que l'identifiant est « difficile à trouver ». Un identifiant n'est pas un mot de passe.
Le prompt à coller dans ton agent pour corriger
Voici le prompt prêt à coller dans Cursor, Claude Code ou Lovable. Adapte les noms de fichiers à ton projet.
Audite mon application pour corriger les failles IDOR (référence directe non sécurisée à un objet).
Contexte : un IDOR survient quand une route récupère un identifiant fourni par l'utilisateur
(URL ou body) et renvoie ou modifie un objet sans vérifier qu'il appartient à l'utilisateur connecté.
Fais ceci, dans cet ordre :
1. Liste toutes les routes API et pages dynamiques qui utilisent un identifiant
(/api/.../[id], ?id=, /[slug], etc.). Pour chacune, indique si elle vérifie
l'appartenance de l'objet à l'utilisateur connecté.
2. Pour chaque route qui ne le fait pas, ajoute une vérification côté serveur.
Récupère l'objet, compare son champ proprietaire/user_id à l'utilisateur authentifié,
et renvoie une erreur 403 si ça ne correspond pas.
3. Si l'app utilise Supabase, active la Row Level Security (RLS) sur toutes les tables
qui contiennent des données utilisateur, puis crée une policy qui restreint
SELECT/UPDATE/DELETE aux lignes dont user_id = auth.uid().
4. Vérifie qu'aucune route ne renvoie d'objet complet avec des champs sensibles
(email, adresse, clés, identifiants de paiement). Réduis les réponses au strict nécessaire.
5. Ne déplace jamais ces vérifications côté client : elles doivent s'exécuter sur le serveur.
Vérifie ensuite que : un utilisateur connecté ne peut lire ou modifier que ses propres
données, et reçoit une erreur 403 (ou un résultat vide) pour toute autre ressource.
Ce prompt fait le tour du problème en une passe. La signature, c'est la dernière phrase : on ne s'arrête pas au constat, on demande à l'agent de vérifier que la faille est fermée.
Les correctifs qui tiennent dans le temps
Un IDOR corrigé peut revenir à la prochaine fonctionnalité. Voici les habitudes qui l'empêchent :
- Le contrôle d'accès côté serveur, toujours. Jamais dans le JavaScript du navigateur, qui se contourne en modifiant une requête.
- La Row Level Security sur Supabase. Active-la dès la création de la table, pas à la mise en prod. Une policy
user_id = auth.uid()couvre la majorité des cas. - Des UUID au lieu d'identifiants séquentiels. Attention : un UUID ne corrige pas un IDOR — il rend juste l'énumération moins triviale. Le vrai correctif reste le contrôle d'appartenance.
- Des réponses minimales. Ne renvoie que les champs dont le frontend a besoin. Moins tu exposes, moins un IDOR est grave.
- Un test automatisé. Pour chaque route sensible, un test qui vérifie qu'un utilisateur B reçoit bien 403 en accédant à la ressource de A.

Questions fréquentes
Quelle est la différence entre IDOR et BOLA ?
BOLA (Broken Object Level Authorization) est le nom utilisé pour l'IDOR quand il concerne une API : une route JSON qui renvoie ou modifie un objet sans vérifier l'autorisation. C'est la même faille de contrôle d'accès, classée dans le Top 10 API de l'OWASP, là où l'IDOR apparaît dans le Top 10 web (catégorie A01).
Est-ce qu'utiliser des UUID corrige une faille IDOR ?
Non. Un UUID rend l'énumération moins pratique qu'un identifiant séquentiel (1, 2, 3…), mais si un UUID fuit — lien partagé, historique, réponse API — n'importe qui peut encore y accéder. L'UUID est un complément, pas un correctif. Le correctif, c'est le contrôle d'appartenance côté serveur.
Comment savoir si mon site a une faille IDOR ?
Liste tes routes qui prennent un identifiant et vérifie, pour chacune, qu'elle compare le propriétaire de l'objet à l'utilisateur connecté. Teste ensuite avec deux comptes : connecté avec A, tente d'accéder à une ressource de B. Si ça passe, la faille est présente. Sur Supabase, vérifie aussi que RLS est activé.
Un IDOR est-il une faille grave ?
Oui, souvent. Un IDOR horizontal peut exposer des données personnelles à grande échelle — il suffit d'énumérer les identifiants — et un IDOR vertical peut donner des droits d'administration. C'est pour ça qu'il figure en tête de la catégorie « contrôle d'accès défaillant » de l'OWASP.
Où se classe l'IDOR dans l'OWASP Top 10 ?
Dans la catégorie A01:2021 — Broken Access Control (contrôle d'accès défaillant), la première du Top 10 web. Pour les API, l'équivalent BOLA figure en position API1 du Top 10 API de l'OWASP.
La bonne nouvelle, c'est que l'IDOR se détecte vite. C'est l'une des failles que Rustine vérifie en scannant ton site comme le ferait un inconnu, avec la preuve : la requête et ce qu'elle renvoie. Si tu veux savoir si ton app renvoie les données des autres, lance un scan gratuit sur rustine.io.