"Notre vélocité a doublé en 6 mois avec Cursor. La sécurité a-t-elle suivi ?" La question m'a été posée par un CTO en avril 2026. Réponse honnête à l'audit : non, pas vraiment. Le code passait les tests unitaires et le SAST standard. Il portait pourtant 8 catégories de défauts que le SAST classique ne sait pas voir, parce qu'elles sont spécifiques au pattern de génération par LLM.
On a fait l'exercice sur 3 missions depuis. Les 8 patterns reviennent. Voilà ce qu'on cherche et comment.
Pourquoi le SAST classique ne suffit pas
SAST (Semgrep, Checkmarx, SonarQube, Snyk Code, Fortify) cherche des patterns de vulnérabilités connues : SQL injection, XSS, mauvais usage de crypto, etc. Très utile, à garder.
Ce que le SAST classique ne voit pas :
- Les incohérences entre couches (ce qui marche unitairement mais foire en composition).
- Les dépendances inventées par le LLM (hallucinations de packages).
- Les validations partielles qui passent les tests heureux mais ratent les edge cases.
- Les autorisations implicites quand le LLM "imagine" un contrôle d'accès cohérent dans une fonction mais l'oublie dans une autre.
Ce sont des défauts de niveau supérieur, plus proches du design que du code line-by-line. D'où l'audit dédié.
Les 8 angles morts à couvrir
1. Dépendances hallucinées
Le LLM invente parfois des packages qui n'existent pas. Pire : il invente un nom qui ressemble à un vrai package et qu'un attaquant a squatté sur npm/PyPI ("slopsquatting").
Comment chercher : pip-audit, npm ls, ou parsing du package.json / requirements.txt croisé avec une liste de packages connus. Vérifier les packages ajoutés dans les 6 derniers mois en regardant : nombre de téléchargements, date de premier release, maintainer connu ou non.
Cas réel observé : un module Python boto3-helpers ajouté par Cursor. N'existait pas il y a 4 mois. Maintainer GitHub inconnu, premier release juillet 2025, 11 stars. Squatte clairement boto3-utils officiel. Suppression immédiate et review de tout ce qu'il a fait pendant qu'il était en prod.
2. Contrôles d'accès incohérents entre endpoints
Le LLM applique correctement RBAC sur /api/users/:id parce que c'est dans le contexte de la conversation. Sur /api/admin/users/:id/reset-password ajouté 3 jours plus tard dans une autre session, il oublie.
Comment chercher : lister tous les endpoints (parsing routes + grep décorateurs), croiser avec une matrice rôle × endpoint. Tout endpoint sans annotation explicite de RBAC = à auditer. Souvent on en trouve 5-15% non protégés sur les API LLM-générées.
3. Validation côté serveur partielle
Le LLM valide souvent côté formulaire (HTML5 / Zod / Pydantic) et oublie la validation symétrique côté serveur. Ou inversement. Ou les deux mais avec des règles différentes.
Comment chercher : pour chaque endpoint, parcourir manuellement les validations côté client et côté serveur. Comparer. Toute divergence = bug.
4. Gestion des secrets dans le code
Le LLM, par paresse de contexte, met parfois un secret en clair en bouchon ("juste pour le développement") et oublie de le remplacer. Surtout sur les exemples qu'il génère.
Comment chercher : gitleaks ou trufflehog en passe systématique sur l'histoire complète. Souvent on en trouve 1-3 sur 50 000 lignes. Voir Secret leak repo public.
5. Logs qui leakent des données sensibles
Le LLM logge volontiers console.log(req.body) ou logger.info(user). Sur les inputs API qui contiennent un mot de passe, un token, un IBAN, une donnée santé : leak silencieux.
Comment chercher : grep des appels log|console|print sur les variables qui contiennent password|token|secret|iban|ssn|email. Filtrage allowlist plutôt que blocklist.
6. Erreurs sans gestion uniforme (info disclosure)
Le LLM remonte parfois les erreurs SQL ou les stack traces complètes dans la réponse HTTP en mode dev, et oublie de les masquer en prod. Aide les attaquants à comprendre votre stack.
Comment chercher : test post-déploiement avec des inputs malformés sur 20 endpoints types. Vérifier que la réponse ne contient ni stack trace, ni nom de table, ni nom de variable interne.
7. Crypto cassée par bonne intention
Le LLM préfère parfois implémenter une crypto custom "plus simple" plutôt que d'utiliser la lib standard. Hash MD5 mentionné dans un commentaire vu ailleurs, AES-ECB par défaut quand on demande "chiffrer", random non-cryptographique pour générer des tokens.
Comment chercher : grep md5|sha1|ECB|Math.random|random.random (pour les contextes où crypto est en jeu). Croiser avec une liste blanche des libs recommandées en interne.
8. Race conditions et états partagés
Le LLM raisonne bien en monothread. En concurrent, il rate :
- Vérifications TOCTOU (check-then-act sans lock).
- Counters incrémentés sans atomic.
- Cache invalidation entre instances.
- Idempotency keys oubliés sur les endpoints POST critiques (paiement notamment).
Comment chercher : revue manuelle sur les endpoints critiques (paiement, génération de tokens, attribution de quotas). C'est l'angle où le LLM est le plus faible et le SAST le moins utile.
Le protocole d'audit en 5 jours
Jour 1 — Préparation et SAST traditionnel
- Snapshot du code à auditer (tag git).
- Lancer Semgrep + Snyk Code + parsing dépendances.
- Sortir un premier rapport de "low-hanging fruits".
Jour 2 — Inventaire IA-spécifique
- Lister tout le code généré sur les 6 derniers mois (heuristiques : commits avec "cursor", "claude", "copilot" dans le message ; ou interview rapide des devs).
- Identifier les zones les plus exposées (API publiques, contact avec données sensibles, paiement, IA).
- Prioriser les 8 angles morts sur les zones les plus exposées.
Jour 3-4 — Revue ciblée
- 1 angle mort par demi-journée, sur 3 à 5 modules.
- Documentation : pour chaque finding, criticité + reproductibilité + correctif proposé.
- Le code généré par LLM se relit étonnamment bien avec un autre LLM en mode "critique" (Claude Opus avec un prompt adversarial). Ça accélère mais ne remplace pas.
Jour 5 — Restitution et plan d'action
- Top 10 des findings critiques avec PoC reproductible.
- 5 quick wins exécutables dans la semaine.
- Recommandations de garde-fous CI/CD pour empêcher la régression.
Les garde-fous CI/CD à ajouter
Une fois l'audit livré, ces 5 garde-fous évitent que les angles morts reviennent :
- Secret scanning (push protection + PR scan).
- SAST sur chaque PR avec règles Semgrep custom.
- SCA sur les dépendances avec alerte sur tout package < 6 mois ou < 1000 téléchargements.
- Linter custom qui flagge les
console.logsur variables sensibles. - Review humaine obligatoire pour les changements sur les modules critiques (paiement, auth, IA).
Le contre-exemple instructif
Une scale-up SaaS B2B m'a contactée 4 mois après avoir migré tout le dev en mode vibe-coding (Cursor + Claude Code). Vélocité doublée, équipe satisfaite. Premier incident : un endpoint admin créé par Cursor sans annotation @requires_admin, accessible depuis 3 semaines. Découvert via un client qui a tâté l'API par curiosité et signalé.
Pas de fuite confirmée. Mais l'audit qui a suivi a trouvé 31 findings sur les 8 angles morts. 9 critiques. Coût de l'audit : 5 jours-homme. Coût d'un incident exploité sur ce même endpoint admin : probablement 6 chiffres et un communiqué client. L'arbitrage budgétaire devient évident.
Pour les règles Semgrep custom, voir Semgrep règles entreprise. Pour comparer les SAST, voir Comparatif Checkmarx vs Semgrep vs SonarQube vs Snyk.