Retour
Produit17 sept. 2026 · 8 min de lecture

Ce que « plus de 190 checks » veut dire concrètement

par detektd team

Gros plan flou d'un écran affichant du code JavaScript sur fond bleu nuit
Photo : Markus Spiske · CC0 · rawpixel

Presque tous les scanners de sécurité affichent un nombre sur leur page d'accueil. Le nôtre dit « plus de 190 checks ». Pris isolément, ce chiffre ne dit rien : un check peut être une vérification profonde qui simule un vrai scénario d'attaque, ou une ligne qui regarde si un en-tête HTTP est présent. Cet article explique ce que ce nombre recouvre chez nous et, surtout, pourquoi la question qui compte n'est pas « combien », mais « lesquels ».

Ce que mesure le Vibe Security Radar

Depuis mai 2025, le Systems Software and Security Lab de Georgia Tech fait tourner le Vibe Security Radar. La méthode, développée par le chercheur Hanqing Zhao, part des bases publiques de vulnérabilités : CVE.org, la National Vulnerability Database, la GitHub Advisory Database et OSV. Pour chaque CVE corrigée, des agents IA remontent l'historique Git jusqu'au commit qui avait introduit le code vulnérable, puis déterminent si ce code avait été produit par un outil d'IA.

Les chiffres de début d'année sont frappants. En janvier 2026, le radar attribuait 6 CVE à du code généré par IA. En février, 15. En mars, 35. Au total, 74 CVE confirmées, soit une multiplication par près de six en deux mois.

0

CVE confirmées et attribuées à des outils de code IA, dont 27 à Claude Code seul (Georgia Tech, mars 2026)

Il faut lire la répartition par outil avec prudence. Claude Code représente 27 des 74 cas, loin devant GitHub Copilot, Cursor, Devin ou Aether. Mais les chercheurs précisent que ce n'est pas nécessairement l'outil le plus fautif : il laisse simplement des signatures identifiables dans les messages de commit, ce qui rend l'attribution possible. Le code écrit par un autre assistant puis committé par un humain est, lui, presque impossible à distinguer. Le biais va donc dans un seul sens : les chiffres sous-estiment le problème.

L'équipe le dit explicitement : 74 est un plancher. Elle estime le nombre réel de failles exploitables introduites par des outils IA à 5 à 10 fois le chiffre confirmé, soit entre 400 et 700 cas rien que dans les dépôts publics observables, sans compter le code d'entreprise privé, impossible à auditer de l'extérieur.

Le chiffre qui compte n'est pas le total

D'autres études convergent, avec des méthodes différentes. La Cloud Security Alliance a testé les modèles de fondation les plus récents et trouvé que 62 % des solutions générées contiennent une faille de conception ou une vulnérabilité connue, y compris avec les modèles les plus à jour. Selon la méthodologie, la fourchette publiée par la CSA en avril 2026 va de 45 % à 70 % d'échantillons qui échouent aux tests de sécurité.

Le bas de cette fourchette correspond au rapport GenAI Code Security de Veracode, publié en 2025, qui a testé plus de 100 modèles sur 80 tâches de code réelles : 45 % des échantillons de code générés introduisaient une vulnérabilité de l'OWASP Top 10. Le détail par catégorie est plus parlant que la moyenne : 86 % des échantillons concernés échouaient à se protéger contre le cross-site scripting, 88 % contre l'injection dans les logs. Java était le langage le plus exposé, avec un taux d'échec de 72 %, contre 38 à 45 % pour JavaScript et Python.

Enfin, une étude menée par Tenzai en décembre 2025 a demandé à cinq plateformes de code IA (Cursor, Claude Code, Replit, Devin et OpenAI Codex) de construire 15 applications. Chacune des cinq, sans exception, a introduit au moins une vulnérabilité SSRF (Server-Side Request Forgery : le serveur peut être amené à faire des requêtes vers une adresse choisie par l'attaquant, y compris vers le réseau interne).

  • Les schémas d'échec dominants ne varient pas selon l'outil ou le langage : autorisations manquantes, contrôles d'accès absents, identifiants écrits en dur, raccourcis dangereux comme eval() pour de l'exécution dynamique.
  • Ce sont des catégories connues depuis vingt ans. Ce qui est nouveau, c'est leur volume : elles se répètent à l'échelle, parce que le code change à chaque génération mais pas la logique qui les produit.

Ce qu'est un check, concrètement

Chez detektd, un check est une hypothèse précise, testée contre l'app en production, qui produit une preuve quand elle échoue. « La clé Supabase exposée peut-elle lire la table orders ? » est un check. « Le fichier .env est-il servi à la racine du site ? » en est un autre. Chaque check a un identifiant, un niveau de sévérité et, depuis septembre, une explication et un correctif rédigés en français et en anglais.

Les checks se répartissent en deux modes. Le scan passif se comporte comme un visiteur ordinaire : il lit ce que le site sert publiquement (pages, bundles JavaScript, en-têtes, fichiers exposés, DNS) et n'envoie aucune donnée. Le scan actif, réservé aux domaines dont vous avez prouvé la propriété, va plus loin : il teste les injections, les contrôles d'accès entre deux comptes, ou le comportement d'un formulaire, en pilotant un vrai navigateur quand l'app en a besoin.

Surtout, les checks ne s'appliquent pas tous à toutes les apps. Le scan commence par détecter la stack réelle (Next.js, Vite, Supabase, un agent IA exposé...), puis active les modules correspondants. Un site statique n'a pas besoin qu'on teste ses policies RLS ; une app Supabase, si.

Des études aux familles de checks

Si les failles du code généré se concentrent dans quelques familles, c'est là qu'un scan doit être le plus dense. Voici comment les catégories citées par ces études se traduisent en vérifications concrètes :

  • Contrôle d'accès manquant : policies RLS Supabase, accès direct aux objets d'un autre utilisateur (IDOR), endpoints d'administration accessibles sans authentification.
  • Identifiants en dur : clés d'API dans les bundles JavaScript (Stripe, OpenAI, AWS...), fichiers .env ou dépôts .git servis publiquement, clés privées à la racine du site.
  • Injections : XSS réfléchi et DOM confirmé dans un navigateur, SQL et NoSQL, injection de templates côté serveur, SSRF.
  • Dépendances et frameworks : versions touchées par des CVE connues, serveurs de développement exposés en production, CVE spécifiques à Next.js ou Vite.
  • Surface IA : prompts système et schémas d'outils envoyés au navigateur, endpoints MCP accessibles sans authentification.

Anatomie d'un check : une clé dans un bundle

Prenons un cas concret, la recherche de secrets exposés, pour voir ce qu'il y a derrière une seule ligne du rapport. Le scan charge la page comme un navigateur, relève tous les scripts référencés, y compris les fragments (chunks) chargés à la demande par les bundlers modernes, puis les télécharge. Sur une app Next.js ou Vite typique, cela représente souvent plusieurs dizaines de fichiers, dont la plupart ne sont jamais chargés sur la page d'accueil.

Dans ces fichiers, la détection s'appuie sur la forme des clés : la plupart des fournisseurs leur donnent un préfixe reconnaissable. Mais trouver une clé ne suffit pas : encore faut-il savoir si elle est censée être publique. C'est là que se jouent la plupart des faux positifs, et où un check doit comprendre le fournisseur :

  • Stripe : une clé pk_live_ est publique par conception (elle sert au paiement côté navigateur) ; une clé sk_live_ ou rk_live_ est secrète et donne accès au compte.
  • Supabase : les anciennes clés sont des JWT. Décoder leur contenu, sans même vérifier la signature, révèle le claim role : anon est normal dans un bundle, service_role est une fuite critique qui contourne toutes les policies. Les nouvelles clés portent un préfixe explicite, sb_publishable_ ou sb_secret_.
  • Fournisseurs d'IA : une clé OpenAI, Anthropic ou Mistral n'a aucune raison légitime d'être servie au navigateur. Sa présence suffit à conclure à une fuite.
Ce que contient une ancienne clé Supabase (payload JWT décodé)
{ "iss": "supabase", "ref": "abcdefghijkl", "role": "anon" }          -> expected, public
{ "iss": "supabase", "ref": "abcdefghijkl", "role": "service_role" }  -> critical: bypasses RLS

Deux règles qui ne se négocient pas

La première : une preuve plutôt qu'une hypothèse. Un check qui signale une faille doit pouvoir montrer la requête et la réponse qui la démontrent. Un XSS n'est rapporté comme confirmé que si le navigateur piloté par le scan l'a effectivement exécuté ; une table Supabase n'est signalée ouverte que si la lecture a réellement renvoyé des lignes. C'est ce qui sépare un rapport exploitable d'une liste de suppositions.

La seconde : ne jamais rien casser. Un scanner qui teste une app en production ne doit ni modifier ses données, ni dégrader son service. Concrètement, cela veut dire des preuves en lecture seule quand c'est possible (pour tester un empoisonnement de cache, par exemple, en utilisant une clé de cache aléatoire qui n'affecte aucun visiteur réel), et un rythme de requêtes qui s'adapte à la latence mesurée du site, pour ralentir dès qu'une petite infrastructure montre des signes de charge.

Ce qu'un chiffre ne dit pas

Un scanner externe a des limites, et il vaut mieux les connaître. Il ne voit pas le code source, seulement ce que l'app expose. Il ne connaît pas la logique métier : il peut détecter qu'un utilisateur lit les commandes d'un autre, mais pas qu'un code promo peut s'appliquer deux fois. Et un nombre élevé de checks peut masquer une faible profondeur, ou un taux de faux positifs qui noie les vrais problèmes.

La bonne question à poser à un scanner

Pas « combien de checks ? », mais : « est-ce que vous testez le contrôle d'accès, les secrets exposés, les injections et les dépendances de MA stack, et est-ce que vous me montrez la preuve quand quelque chose échoue ? »

C'est la conclusion commune de toutes ces études : les failles du code généré par IA ne sont presque jamais exotiques. Ce sont les mêmes catégories, répétées à une vitesse inédite. La réponse n'est pas un chiffre plus gros, c'est une couverture systématique de ces catégories, sur la stack réellement détectée, à chaque déploiement.

Ce que « plus de 190 checks » veut dire concrètement | detektd