Angle mort de sécurité.
Les assistants IA produisent du code fonctionnel qui omet silencieusement les contrôles de sécurité qu'un humain ajouterait par habitude — validation des entrées, autorisation, encodage des sorties, gestion des secrets — parce que « ça compile et ça renvoie 200 » ressemble à du travail terminé.
##Signs and Symptoms
Un relecteur repère un angle mort de sécurité lorsque le code fonctionne sur le chemin heureux mais que les contrôles qu'un humain soucieux de sécurité ajoute par réflexe sont tout simplement absents. Le modèle démontre la fonctionnalité, pas la défense. Signes révélateurs :
- Requêtes / commandes construites par concaténation de chaînes au lieu d'être paramétrées (points d'injection SQL / commande / LDAP).
- L'entrée utilisateur va vers la sortie sans encodage (XSS réfléchi/stocké) ou vers
fs/child_process/fetchsans liste d'autorisation (traversée de répertoire, SSRF). - L'endpoint authentifie mais n'autorise jamais — il vérifie qui vous êtes, jamais si vous avez le droit de toucher cet enregistrement (IDOR / contrôle d'accès au niveau objet rompu).
- Secrets codés en dur — clés d'API, jetons, mots de passe de base de données inscrits en ligne « pour que ça tourne ».
- Contrôles absents par omission : pas de jeton CSRF, pas d'en-têtes de sécurité, pas de limitation de débit, cryptographie faible/héritée (MD5, SHA-1,
Math.random()pour les jetons). - Théâtre de commentaires : un commentaire
// validate inputou// TODO: add authtrône là où devrait se trouver la vraie vérification — OX a trouvé des commentaires redondants dans 90 à 100 % du code IA, tenant souvent lieu de la logique manquante.
// Handler Express généré par IA — a l'air complet, livre trois failles
app.get("/api/orders/:id", authMiddleware, async (req, res) => {
const apiKey = "sk_live_8f3b2a91c7d44e0f"; // 1. secret codé en dur
const order = await db.query(
`SELECT * FROM orders WHERE id = ${req.params.id}` // 2. injection SQL
);
res.send(`<h1>Order for ${order.customerName}</h1>`); // 3. XSS réfléchi
// note: authMiddleware prouve la connexion, ne vérifie jamais order.userId === req.user.id (IDOR)
});
Quatre vulnérabilités distinctes, zéro test en échec — l'odeur est ce qui n'est pas là.
##Reasons for the Problem
Pourquoi les modèles le produisent
- La cible d'entraînement est la plausibilité, pas la sûreté. La prédiction du token suivant optimise la manière la plus courante d'écrire du code, et les corpus publics sont saturés d'extraits de niveau tutoriel, à requêtes concaténées et sans autorisation. OX Security note que les modèles "adoptent par défaut des approches non sécurisées parce qu'elles sont les plus fréquentes dans les données d'entraînement." Carnegie Mellon a constaté que 61 % des extraits produits par l'IA fonctionnent mais que seulement ~10,5 % passent une revue de sécurité.
- « Terminé » se définit par le chemin heureux. Un LLM optimise pour que la requête visible aboutisse. Les contrôles de sécurité ne produisent aucun signal positif lors d'une exécution rapide, ils sont donc abandonnés — ce qu'OX appelle « l'insécurité par ignorance » : du code fonctionnel auquel manquent des garde-fous parce qu'aucune des personnes impliquées ne savait ce qui était requis.
- Aucun contexte du dépôt. Le modèle ne voit pas votre helper
authorize(), votre schéma de validation ni votre gestionnaire de secrets, alors il inline une clé littérale ou saute la vérification plutôt que de réutiliser un contrôle existant. - Complaisance + vélocité. Il renvoie exactement ce que vous avez demandé ("ajoute un endpoint de commande"), pas le modèle de menace qui l'entoure, et les goulots d'étranglement comme la revue et la modélisation des menaces sont précisément ce que le développement à la vitesse de l'IA supprime — la conclusion centrale d'OX est que c'est la vélocité, et non le taux de défauts par ligne, qui envoie du code vulnérable en production.
- Obsolescence due à la date de coupure d'entraînement. Les modèles recourent à des schémas de cryptographie et de bibliothèques qui étaient acceptables il y a des années (MD5, SHA-1, options TLS dépréciées, anciens flux d'authentification).
Pourquoi c'est nuisible
- Exploitabilité directe. Études indépendantes citées par OX : ~62 % du code généré par l'IA est livré avec une vulnérabilité ; 86 % ont échoué aux défenses contre le XSS (CSET/Georgetown) ; CodeRabbit a mesuré 2,74× plus de XSS que dans le code humain ; Tenzai a constaté que 0 application sur 15 construites par l'IA définissait des en-têtes de sécurité ou une protection CSRF ; Escape.tech a trouvé plus de 400 secrets exposés dans 5 600 applications « vibe-codées ».
- Invisible aux tests comme aux lecteurs. Un contrôle d'autorisation manquant n'a aucun test en échec ni aucun diff sur lequel pointer, il passe donc la revue sans encombre — et le volume de sortie de l'IA fait que la revue ne peut pas monter en charge pour l'attraper.
- Dette technique cumulative. Les données de GitClear (le refactoring est passé de 25 % à moins de 10 % des lignes modifiées, le copier-coller en hausse dépasse désormais les lignes déplacées, les blocs dupliqués multipliés par ~8) signifient que le même schéma non sécurisé est cloné à travers la base de code, multipliant le rayon d'impact de tout angle mort isolé.
##Treatment
Tactiques de revue et de prompting
- Nommez le modèle de menace dans le prompt. "Écris cet endpoint en supposant que l'
idest contrôlé par un attaquant ; impose une autorisation au niveau objet, paramètre toutes les requêtes, encode toutes les sorties et lis les secrets depuisprocess.env." Spécifier l'adversaire inverse le comportement par défaut. - Forcez la réutilisation des contrôles existants. "Utilise notre helper
authorize(user, 'order', id)et le validateurorderSchema— n'écris pas de nouvelle validation." Cela contre directement la cause de l'absence de contexte du dépôt (et l'odeur connexe de Code dupliqué). - Faites exécuter les outils par le modèle. Exigez qu'il lance
semgrep --config p/owasp-top-ten,gitleaks detect,npm auditet votre configurationeslint-plugin-security, puis qu'il corrige ce qu'ils signalent avant de se déclarer terminé. - Demandez explicitement les négatifs. "Liste les préoccupations d'authentification, d'autorisation, de validation des entrées, d'encodage des sorties et de gestion des secrets pour ce handler, et montre où chacune est appliquée." Un blanc dans cette liste est le bug.
- Modélisez la menace du diff, pas de la ligne. Les failles dangereuses sont des omissions ; relisez donc en demandant "quel contrôle devrait être ici et ne l'est pas ?" plutôt qu'en cherchant de mauvaises lignes.
Le refactoring — paramétrer la requête (tue l'injection), encoder la sortie (tue le XSS), ajouter un contrôle d'autorisation au niveau objet (tue l'IDOR) et Extraire le secret en ligne vers la configuration :
// APRÈS
app.get("/api/orders/:id",
authMiddleware,
validate(orderParamsSchema), // validation des entrées
async (req, res) => {
const order = await db.query(
"SELECT * FROM orders WHERE id = $1", [req.params.id] // paramétré
);
if (!order || order.userId !== req.user.id) { // autorisation au niveau objet
return res.sendStatus(404);
}
res.json({ customerName: order.customerName }); // sortie structurée, encodée automatiquement
}
);
// secret : process.env.STRIPE_API_KEY, chargé une fois au démarrage, jamais inline
Là où l'odeur s'est propagée par clonage, corrigez-la une fois et appliquez Extraire une fonction sur le contrôle (requireOrderOwnership, escapeHtml) afin que chaque site d'appel partage une seule implémentation auditée plutôt que N copies.
##Detected by
- Gitleaks hardcoded secrets / generic-api-key
- Semgrep p/owasp-top-ten (e.g. sql-injection, xss, dangerous formatstring sinks)
- GitHub CodeQL js/sql-injection, js/xss, js/hardcoded-credentials, js/path-injection
- eslint-plugin-security detect-non-literal-fs-filename, detect-child-process, detect-eval-with-expression, detect-object-injection
- Bandit (Python) B105 hardcoded_password_string, B608 hardcoded_sql_expressions, B324 weak hashlib
- SonarQube / SonarSource Security Hotspots & Vulnerability rules (injection, weak cryptography, hardcoded credentials)
- npm audit / OWASP Dependency-Check known-vulnerable dependency detection