L'angle mort de l'assistant IA : qui a le droit de toucher à votre infra
par detektd team

Le mode Auto-Run de Cursor existe pour une raison simple : arrêter de demander confirmation à chaque commande. Un agent qui travaille sur un projet lance des dizaines de commandes par tâche : lire l'état du dépôt, lancer les tests, installer une dépendance. Les valider une par une devient vite insupportable. Cursor propose donc une allowlist : vous approuvez une fois une liste de commandes jugées sûres (git status, npm test, git branch...), et l'agent les exécute ensuite sans repasser par vous.
CVE-2026-22708, publiée sous l'avis de sécurité GHSA-82wg-qcm4-fp2w, montre pourquoi cette confiance était mal placée. Avant la version 2.3, quand l'agent tournait en Auto-Run avec l'allowlist activée, certaines commandes internes du shell pouvaient s'exécuter sans figurer dans l'allowlist et sans demander d'approbation.
Commandes externes et built-ins
Pour comprendre la faille, il faut distinguer deux familles de commandes. git, npm ou curl sont des programmes externes : le shell les cherche sur le disque et les lance dans un nouveau processus. D'autres commandes, les « built-ins », font partie du shell lui-même : ce sont celles qui définissent une variable d'environnement, créent un alias ou changent de répertoire. Elles ne lancent aucun programme : elles modifient l'état du shell dans lequel tourneront toutes les commandes suivantes.
L'allowlist de Cursor vérifiait les commandes externes. Les built-ins, eux, n'étaient pas soumis à la même vérification. Or de nombreux programmes, git en tête, adaptent leur comportement à des variables d'environnement : où chercher leur configuration, quels programmes auxiliaires appeler. Modifier l'environnement, c'est donc pouvoir changer ce que fera une commande pourtant approuvée.
Le nom de la commande n'est pas la commande
Le scénario d'attaque découle directement de là. L'allowlist vérifie quelle commande va s'exécuter, pas dans quel environnement. Un attaquant capable de mettre du texte sous les yeux de l'agent (un README, un fichier de dépendance, un commentaire d'issue GitHub, c'est-à-dire une injection de prompt indirecte) peut l'amener à exécuter un built-in qui modifie silencieusement une variable d'environnement. Aucune approbation n'est demandée. La commande suivante, elle, figure bien sur l'allowlist. Sauf qu'avec un environnement empoisonné, une commande aussi anodine que git branch exécute le code de l'attaquant.
Aucune alerte ne se déclenche. Du point de vue de Cursor, une commande approuvée vient de s'exécuter normalement. Du point de vue du développeur, l'agent a simplement listé les branches du dépôt. C'est ce qui rend la faille si difficile à repérer : elle ne laisse aucune trace dans l'interface.
Une leçon que sudo avait déjà apprise
Le problème n'a rien d'inédit. Les administrateurs Unix le connaissent depuis des décennies à travers sudo, qui permet précisément d'autoriser certaines commandes pour certains utilisateurs : une allowlist. Et sudo a dû résoudre exactement la même question : si l'utilisateur peut transmettre ses variables d'environnement à une commande autorisée, il peut en changer le comportement. C'est pour cette raison que sudo réinitialise l'environnement par défaut (l'option env_reset) et impose un chemin de recherche des programmes contrôlé (secure_path).
Les agents de code ont réinventé l'allowlist sans reprendre cette leçon. Et contrairement à un utilisateur humain de sudo, un agent peut être manipulé par n'importe quel texte qu'il lit.
Pas un cas isolé
CVE-2026-22708 n'est pas arrivée seule. Dans la même période, deux failles voisines ont été corrigées dans Cursor : CVE-2026-26268, une évasion via les git hooks (des scripts que git exécute automatiquement à certaines étapes), et CVE-2026-21523, une condition de course de type TOCTOU (« time of check to time of use ») : l'état vérifié n'est plus celui qui est utilisé au moment de l'exécution.
Les trois partagent la même faiblesse structurelle : un modèle de permissions qui vérifie une commande, un chemin ou un identifiant à un instant donné, sans garantir que l'environnement autour n'a pas changé entre la vérification et l'exécution. Docker a d'ailleurs consacré à ce thème un billet au titre explicite : « la commande que vous aviez déjà approuvée ».
- Une allowlist vérifie une identité (le nom d'une commande), pas une intention.
- Elle suppose que l'environnement d'exécution est sain, une hypothèse qu'un simple fichier texte peut casser.
- Elle ne couvre pas l'écart entre le moment où une commande est validée et celui où elle s'exécute réellement.
Ce qu'une allowlist solide doit contrôler
Une allowlist qui compare le début d'une ligne de commande à une liste de noms part avec un handicap structurel : la ligne passe ensuite par un shell, qui a sa propre grammaire. Enchaînements, sous-commandes, redirections, variables : une seule ligne « autorisée » peut contenir bien plus qu'une commande. CVE-2026-22708 exploitait une autre facette du même problème (l'état du shell entre deux commandes), mais la leçon est la même : le shell interprète, et c'est cette interprétation qu'il faut contrôler.
Les outils qui exécutent des commandes de façon sûre font l'inverse : ils ne passent pas par un shell. Ils lancent directement un exécutable, désigné par son chemin absolu, avec une liste d'arguments séparés, un répertoire de travail fixé, une durée maximale, et surtout un environnement construit explicitement plutôt qu'hérité. C'est le même principe que l'option env_reset de sudo, appliqué au code :
import { execFile } from "node:child_process";
import { homedir } from "node:os";
execFile(
"/usr/bin/git", // absolute path: no PATH lookup
["branch", "--list"], // arguments, never a shell string
{
cwd: repoDir,
timeout: 10_000,
env: { PATH: "/usr/bin:/bin", HOME: homedir() }, // built, not inherited
},
callback,
);Ce schéma ferme la classe de failles de CVE-2026-22708 : aucune variable posée par une commande précédente ne peut atteindre la suivante, puisque chaque exécution reçoit un environnement neuf. Le même résultat s'obtient en ligne de commande avec env -i, qui démarre un programme avec un environnement vide :
env -i PATH=/usr/bin:/bin HOME="$HOME" git branch --list
Le dépôt lui-même est une entrée non fiable
Reste un point que CVE-2026-26268 met en lumière : git lit la configuration locale du dépôt dans lequel il s'exécute, et cette configuration peut désigner des programmes à lancer automatiquement ; les hooks en sont l'exemple le plus connu. Ouvrir un dépôt non fiable et y lancer git, même une commande en lecture, n'est donc pas neutre. Git a déjà dû traiter ce problème : en 2022, CVE-2022-24765 a conduit à l'option safe.directory (Git 2.35.2), qui fait refuser par défaut à git les dépôts appartenant à un autre utilisateur du système. Pour un agent, l'équivalent est de traiter tout dépôt fraîchement cloné comme une entrée non fiable, au même titre qu'un README.
La vraie question : ce que l'agent peut atteindre
Le correctif est disponible depuis Cursor 2.3, et c'est la première chose à vérifier. Mais la leçon dépasse cette faille. Sur la machine d'un développeur, le shell de l'agent a généralement accès à tout ce que le développeur possède : identifiants cloud, clés SSH, jetons npm ou GitHub, parfois une connexion à la base de production. Une allowlist contournée ne donne pas accès à « l'agent » : elle donne accès à tout cela.
- Mettre Cursor à jour (2.3 ou plus récent). En attendant, désactiver Auto-Run ou exiger une confirmation pour toute commande shell.
- Faire travailler l'agent dans un environnement séparé (devcontainer, machine virtuelle) qui ne contient pas vos identifiants personnels.
- Ne jamais laisser d'identifiants de production sur un poste de développement ; préférer des accès temporaires, obtenus à la demande.
- Être particulièrement prudent avec Auto-Run sur un dépôt fraîchement cloné ou une nouvelle dépendance : c'est exactement là que se cache le texte non fiable.
Le bon réflexe
Avant de valider une allowlist, posez-vous la question inverse : si cette commande exécutait autre chose que ce que je crois, qu'est-ce qu'elle pourrait atteindre depuis ce shell ? Si la réponse inclut la production, le problème n'est pas l'allowlist.
