Un bot de revue de code propulsé par IA rejette un correctif en inventant une CVE inexistante
Le 29 octobre 2026, Docker raconte comment un bot de revue de code tournant en local via Ollama a refusé un simple bump de version PostgreSQL en citant une CVE qui n’a jamais existé. La leçon vaut pour toute équipe qui branche un agent d’IA sur sa pipeline : la sortie d’un agent est une entrée non fiable, qu’il faut étiqueter et vérifier comme telle.
29 octobre 2026. Docker publie le sixième épisode de sa série AI Coding Agent Horror Stories. 1 500 — le nombre de mots du rapport par lequel un bot de revue a refusé un correctif de sécurité banal. Zéro — le nombre de failles réelles que ce rapport décrivait. Le point qui compte : un agent en lecture seule, incapable de rien exécuter, a quand même failli déclencher une révocation massive d’accès — non par ses permissions, mais par l’autorité de sa prose.
La revue qui a tout inventé
Un ingénieur plateforme construit un bot de revue de code pour son équipe. Le principe est simple : à chaque push, le bot lit les changements et rédige une revue dans la pipeline, comme le ferait un collègue avant la relecture humaine. Il le nomme BuaJi — en Inde, la bua, la sœur du père, est cette parente qui inspecte tout et finit toujours par trouver un défaut. Le nom est de circonstance.
Le montage est rigoureux. Le bot tourne sur des modèles locaux via Ollama : les poids restent sur le matériel de l’ingénieur, aucune requête ne part vers un fournisseur d’IA, et le code source de l’entreprise ne quitte jamais le bâtiment. Il s’exécute comme un job de la CI, déclenché à chaque push. Surtout, il reçoit une règle stricte : lire et commenter, rien de plus. Il ne peut pas lancer terraform apply, ni kubectl apply, ni pousser un commit. Sur le papier, c’est exactement comme on voudrait construire un relecteur d’IA.
Un bump de version qui aurait dû passer en trois secondes
Le changement en question est aussi banal que responsable. Le produit embarque une copie de PostgreSQL, et les anciennes versions publiées traînent des vulnérabilités référencées par des CVE. L’ingénieur fait donc monter la version :
- POSTGRES_VERSION=16.11
+ POSTGRES_VERSION=16.13 Quelques lignes, un numéro de version, un seul but : fermer des failles déjà publiques. N’importe quel relecteur, humain ou machine, devrait approuver en quelques secondes. Il n’y a rien de suspect dans ce diff — et c’est précisément ce qui rend la suite instructive.
Un rapport convaincant, entièrement faux
BuaJi répond par un rapport d’environ 1 500 mots qui refuse le changement. Pour référence, un commentaire de revue normal tient en une ou deux phrases. Le rapport qualifie le bump de version d’« architectural takeover », une modification structurelle glissée dans le code sous couvert de maintenance de routine. Il affirme que la nouvelle version de PostgreSQL sert de véhicule pour exfiltrer des données internes vers une entreprise tierce — qu’il nomme. Cette entreprise n’existe pas.
Le bot va plus loin. Il cite des ressources Kubernetes par leur nom, comme s’il avait inspecté le cluster — ces ressources n’ont jamais existé, et BuaJi n’avait aucun accès au cluster pour y regarder. Il rédige des scripts Go pour « isoler les nœuds PostgreSQL infectés », alors que rien n’est infecté. Il recommande enfin de révoquer immédiatement tous les accès IAM, une action qui verrouillerait l’organisation entière, y compris les personnes nécessaires pour réparer un vrai problème.
Ce qui tient tout l’édifice, c’est un numéro de CVE qui n’a jamais été émis par quiconque. C’est le détail à retenir : un identifiant CVE est l’une des choses les plus faciles à vérifier en sécurité, puisqu’il se consulte dans un registre public en quelques secondes. Le bot a inventé un fait précisément là où les faits inventés sont les plus faciles à attraper — et pourtant le rapport semblait irréprochable : Markdown propre, YAML syntaxiquement valide, ton urgent et assuré de l’ingénieur sécurité chevronné qui a trouvé quelque chose de grave. L’ingénieur met deux minutes à lire les logs, comprend que tout est faux, et retourne à ses affaires.
Le piège n’est pas la permission, c’est l’autorité
Il faut le dire clairement : la règle de lecture seule a fonctionné. BuaJi ne pouvait exécuter aucune de ses propres recommandations, et n’a jamais rien touché. L’épisode n’a coûté que deux minutes de soirée. Le problème, c’est que la règle ne contrôlait que ce que le bot pouvait faire — personne n’avait pensé à ce qu’il pouvait dire. Un agent en lecture seule reste autorisé à donner des ordres, et la personne qui lit sa sortie dispose en général exactement des accès que l’agent s’est vu refuser.
Ce cas n’est pas dangereux à cause d’une permission violée — aucune ne l’a été. L’agent est resté dans son périmètre, l’ingénieur avait le droit d’exécuter ces commandes sur ses propres systèmes, et la seule chose fausse de toute la chaîne était le contenu du rapport. Imaginez maintenant un ingénieur plus jeune, d’astreinte à deux heures du matin, à moitié réveillé, qui lit un long rapport de sécurité alarmant dans la pipeline. Révoquer tous les accès IAM en production en pleine nuit est une panne à soi seul ; exécuter un script Go non relu contre ses nœuds de base de données peut être bien pire. Dans les deux cas, BuaJi n’aurait rien fait. Une personne aurait tout fait, de bonne foi, parce que le rapport le lui demandait.
La sortie d’un agent est une entrée non fiable
La leçon de Docker tient en une phrase : un bac à sable n’est pas un vérificateur de faits. Aucune frontière de microVM ne rendra jamais un commentaire exact. Ce qu’une frontière change, c’est ce que la sortie fabriquée peut faire une fois qu’elle existe. Les Docker Sandboxes font tourner les agents dans des microVM isolées, chacune avec son noyau, son système de fichiers et un réseau qui refuse tout par défaut : une invention n’a nulle part où aller, aucun identifiant à utiliser, aucun cluster à joindre, tant que personne n’a accordé l’accès au préalable. La règle de lecture seule cesse d’être une convention mémorisée et devient une propriété de l’environnement.
Mais cela protège de l’agent, pas de l’humain qui lit sa sortie — et aucun bac à sable ne le fera jamais. Pour cette moitié-là, la sortie d’un agent se traite comme on traite déjà son entrée : non fiable jusqu’à preuve du contraire. Concrètement, étiquetez-la pour qu’elle ne porte pas le poids d’un collègue, vérifiez tout numéro de CVE cité, et n’exécutez jamais une remédiation écrite par un agent avant qu’un humain ne l’ait lue et comprise.
Verdict
Si vous branchez un relecteur d’IA sur votre pipeline, appliquez-lui le même traitement qu’à ses entrées : étiquetez sa sortie comme non fiable et vérifiez chaque CVE citée avant toute action — le cas BuaJi montre qu’une recommandation urgente et bien formatée peut être intégralement fabriquée, et qu’une révocation IAM sur un rapport halluciné est une panne à part entière. Si vos agents doivent agir, faites-les tourner dans un environnement isolé de type sandbox microVM, où la frontière devient une propriété du système et non une convention que quelqu’un finira par oublier. Et si vous êtes la personne qui lit un rapport d’IA alarmant à trois heures du matin, ne touchez à rien avant d’avoir vérifié l’identifiant dans un registre public : c’est la seule action de ce récit qui coûte deux minutes au lieu d’une nuit.