git status a exécuté leur code
Le 2 septembre 2026, Manifold Security a divulgué GitSpawn : huit failles réparties sur sept agents de codage en ligne de commande, où le .git/config d'un dépôt exécute une commande sur la machine du développeur. L'agent lance git status pour savoir sur quelle branche il se trouve, git rafraîchit son index, et la commande choisie par le dépôt s'exécute avec les privilèges de l'utilisateur connecté, hors du bac à sable, avant l'invite de confiance, et sur un outil avant même la connexion. Aucune invite, aucun appel d'outil, aucun tour de modèle. Bromure Agentic Coding ne corrige pas ce chemin. Il déplace la machine à laquelle ce chemin mène.
Vous n'avez rien tapé et rien approuvé. L'agent n'avait pas fini de démarrer, et sur l'un de ces outils vous n'étiez même pas connecté. Un dossier que quelqu'un vous a envoyé a exécuté une commande en votre nom, et c'est git qui l'a exécutée.
Un prestataire termine un travail et vous envoie un zip du répertoire du projet
dans un dossier partagé. Vous le dézippez, vous faites cd dedans, et vous
démarrez votre agent de codage pour vous orienter. L'agent commence par demander
à git de quelle branche il s'agit et ce qui est modifié. C'est tout l'exploit.
Le 2 septembre 2026, The Hacker News a rapporté une divulgation de Manifold Security couvrant huit failles réparties sur sept agents de codage en ligne de commande, publiée sous le nom de GitSpawn. À eux tous, les outils concernés totalisent près d'un demi-million d'étoiles GitHub, et Claude Code à lui seul a dépassé les 77 millions de téléchargements npm par mois. Quatre des huit exécutaient encore des commandes fournies par le dépôt quand Manifold les a retestés le 1er septembre.
Un réglage de performance dont la valeur est une commande
core.fsmonitor est une option de git destinée aux gens qui ont des dépôts
énormes. Plutôt que de parcourir tout l'arbre pour savoir ce qui a changé, git
peut appeler un programme auxiliaire externe et le lui demander. La valeur du
réglage est la commande. Git la lit dans le .git/config du dépôt lui-même et
l'exécute chaque fois qu'il rafraîchit son index, c'est-à-dire sur git status,
sur git diff, sur la plomberie sur laquelle s'appuie chaque outil.
Presque tous les agents examinés par Manifold rassemblent le contexte du projet
en lançant ces commandes au démarrage, et aucun d'eux ne regardait d'abord le
.git/config. Le dépôt nomme donc la commande et git l'exécute. Dans les mots
des chercheurs, elle s'exécute « avec l'intégralité des privilèges de
l'utilisateur connecté, hors du bac à sable ». OpenAI, dans son propre avis de
sécurité pour la variante Codex, a indiqué que l'auxiliaire « s'exécute hors du
bac à sable de commandes de Codex et sans invite d'approbation de
l'utilisateur ».
Un git clone n'emporte rien de tout cela. Le clone transfère des objets et des
références, et la configuration locale du dépôt source reste chez elle. Le
projet empoisonné doit donc vous parvenir sous forme de fichiers, avec son
répertoire .git intact : une archive zip, un disque partagé, un dossier
synchronisé, une clé USB. La liste de Manifold décrit la façon dont les
consultants, les clients et les collègues se transmettent du travail, et c'est
le seul chemin de livraison où il n'y a aucune pull request. La protection de
git contre les dépôts hostiles, safe.directory, vérifie si le dépôt appartient
à quelqu'un d'autre. C'est vous qui l'avez dézippé, il vous appartient donc, et
la protection n'a rien à dire.
Le calendrier place la protection propre à chaque agent une étape trop tard. Sur Claude Code et Hermes Agent, la charge se déclenche avant l'invite de confiance de l'espace de travail, la boîte de dialogue qui existe précisément pour demander si vous faites confiance à ce répertoire. Sur Qwen Code, elle se déclenche avant que l'utilisateur se soit authentifié, et sur Grok Build, elle se déclenche à la première frappe.
Huit constats, sept agents, quatre encore ouverts
La moitié est corrigée. goose 1.44.0 embarque le correctif de
CVE-2026-72718, notée CVSS 7.0.
OpenAI a livré Codex CLI 0.131.0 et les builds bureau 26.519.x pour
CVE-2026-19592. Cursor a corrigé sa variante. Manifold a confirmé le chemin
core.fsmonitor de Claude Code en 2.1.193 et Anthropic l'a fermé en 2.1.196,
sans publier d'avis de sécurité : Manifold note qu'aucun des deux constats
concernant Claude Code n'apparaît dans les registres d'avis de npm.
L'autre moitié n'a pas bougé. Hermes Agent a un CVE (CVE-2026-71963) et un avis
privé toujours non trié après six tentatives de contact. Les mainteneurs de Qwen
Code ont accepté le rapport le 7 juillet et 0.22.3 exécute toujours la commande.
Grok Build l'exécute toujours. Et Claude Code a un second chemin, via sa
commande ultrareview, qui détourne une autre clé de configuration git et était
toujours actif en 2.1.252. Manifold a retenu le nom de cette clé plutôt que de
distribuer un modèle d'attaque réutilisable.
Anthropic a corrigé le premier chemin en trois jours. La classe de failles l'a contourné par une autre clé, dans le même fichier, dans le même produit.
C'est la surface d'exécution de git, héritée par tous les outils qui délèguent à
git, et git a plus d'un réglage dont la valeur est une commande qu'il exécutera
pour vous. Les pagers, les éditeurs, les commandes SSH, les chemins de hooks,
les pilotes de diff et de filtre, et les alias commençant par une échappée shell
prennent tous des valeurs de commande. Chaque éditeur doit maintenant
déterminer, clé par clé, lesquelles un dépôt peut atteindre depuis son chemin de
démarrage, face à un schéma de configuration qui gagne des clés avec le temps.
Le correctif recommandé par Manifold, assainir la configuration git pendant les
opérations de contexte en arrière-plan et désactiver core.fsmonitor, est une
liste de refus maintenue face à un espace de noms. Les chercheurs ont trouvé le
motif dans plus d'agents que le rapport n'en nomme.
Les contrôles qui auraient dû rattraper ça sont en aval
Alignez ce dont dispose aujourd'hui une équipe rigoureuse sur un agent de codage : les invites de permission sur l'usage des outils, la confiance de l'espace de travail, les hooks qui inspectent une commande avant son exécution, les points d'accès de transcript qui expédient une session vers un backend de conformité, et OpenTelemetry pour les décisions de permission et les contournements.
Tous s'ancrent à la boucle propre de l'agent, c'est-à-dire à un appel d'outil
que l'agent a décidé de faire ou à un tour que le modèle a pris. GitSpawn ne
produit ni l'un ni l'autre. Le processus qui exécute la charge est git,
invoqué par l'agent pour sa propre intendance, et la commande vient d'un fichier
que l'agent n'a jamais lu. Il n'y a aucun appel d'outil à approuver et aucun
hook à déclencher. Une équipe qui regarde les transcripts d'agent atterrir dans
son SIEM voit une session qui démarre normalement et ne montre rien, le même
angle mort dont nous parlions
quand Anthropic a livré son API Compliance :
un journal ancré à ce qui a atteint le modèle ne peut pas voir ce qui s'est
exécuté avant que le modèle soit consulté.
La commande va s'exécuter. La question qui vaut la peine d'être posée, c'est ce qu'elle va trouver.
Exécutez-la et voyez ce qu'elle trouve
Bromure Agentic Coding donne à chaque espace de travail sa propre VM Ubuntu sous l'hyperviseur d'Apple. L'agent, son git, son gestionnaire de paquets, et tout ce que ces trois-là démarrent vivent dans l'invité. Déposez le zip du prestataire dans un espace de travail, laissez l'auxiliaire se déclencher, et accordez tout à l'attaquant : avant la confiance, avant l'authentification, root dans l'invité si vous voulez.
Lire les clés SSH. Il n'y en a aucune à lire. Les clés privées d'un espace
de travail restent sur votre Mac ; la VM reçoit un SSH_AUTH_SOCK ponté par
vsock vers un agent côté hôte. Ce protocole a une requête qui signifie « signe
ce défi » et aucune requête qui signifie « donne-moi la clé ».
Balayer l'environnement à la recherche d'identifiants. Ils y sont tous,
formatés comme les validateurs l'attendent, et tous sont des leurres.
ANTHROPIC_API_KEY contient un faux sk-ant-api03-brm-…, et il en va de même
pour ~/.git-credentials, ~/.aws/config, ~/.kube/config et
~/.docker/config.json. Vos vraies valeurs vivent chiffrées sur votre Mac, et
le proxy les substitue sur le fil après que la requête a quitté la VM,
uniquement lorsqu'elle est destinée à l'hôte pour lequel cet identifiant a été
frappé. Aucun interrupteur ne désactive cela. C'est ainsi que fonctionnent les
identifiants dans l'application.
Télécharger le second étage. L'auxiliaire est un chargeur, quelques
centaines d'octets dont le travail est d'aller chercher la vraie charge. Cette
requête se heurte au pare-feu de sortie de l'espace de travail. Réglez le
Trafic non apparié sur Deny et la VM atteint les hôtes que vous avez listés
et rien d'autre, appliqué à deux endroits : le commutateur virtuel filtre par IP
de destination et par nom d'hôte reniflé dans le DNS, tous protocoles confondus,
et le proxy filtre à nouveau par nom de serveur TLS et, pour les règles web,
par méthode HTTP. Un chargeur qui se tourne plutôt vers un registre de paquets
rencontre le pipeline de chaîne d'approvisionnement, où la barrière d'âge refuse
les versions plus jeunes que le seuil. Une charge publiée hier ne peut pas
franchir cette barre.
Exfiltrer ce qu'il a trouvé. Là, quelque chose doit traverser un fil que votre Mac possède. Le proxy analyse chaque requête sortante par rapport aux leurres frappés pour l'espace de travail, en-têtes et corps, avec un automate d'Aho-Corasick. Un leurre adressé à un hôte hors de la portée pour laquelle il a été frappé est la signature d'une machine qui envoie quelque chose qu'elle ne devrait pas connaître. Le proxy bloque avec un HTTP 451 avant qu'un seul octet n'atteigne la destination, met la VM en pause, et lève une alerte nommant l'identifiant et les deux hôtes. Bromure marque ensuite l'espace de travail comme compromis, et il ne redémarrera pas tant que vous n'aurez pas effacé son disque et son home.
Laisser de la persistance. Un .bashrc modifié dans l'invité dure aussi
longtemps que vous laissez durer la VM. Effacer le home réinitialise
/home/ubuntu, Réinitialiser le disque reclone le disque système depuis
l'image de base signée, et bromure-cli vm run --rm vous donne un espace de
travail qui se supprime lui-même à l'arrêt de la VM.
L'interception n'a aucune variable d'environnement à désactiver
Un proxy auquel l'invité adhère est un proxy que l'invité peut décliner. Le
commutateur virtuel de Bromure détourne lui-même les flux port 80 et port
443 de la VM vers le proxy hôte : aucun HTTPS_PROXY à désactiver, rien
dans l'invité qui l'éteigne, et le HTTP en clair inspecté comme l'est le
HTTPS. Le processus qui fait la requête ici n'a jamais lu la configuration
de l'agent et n'est pas l'agent. C'est un binaire auxiliaire lancé par git,
et il emprunte le même fil que tout le reste.
La ligne existe même si aucun appel d'outil n'existe
Le proxy hôte écrit un enregistrement de métadonnées pour chaque requête
sortant de la VM, quel que soit le processus qui l'a faite : heure, hôte,
port, méthode, chemin, statut, latence, et octets mesurés avant la
substitution de l'identifiant. Les verdicts du pare-feu, les décisions de
chaîne d'approvisionnement et le courtage d'identifiants atterrissent dans
la Chronologie de sécurité (Fenêtre → Chronologie de sécurité…), et sur
un Mac inscrit ils partent vers le flux d'événements de l'organisation sous
egress.firewall, supply_chain.fetch et credential.exfiltration. Un
transcript côté agent de cette attaque est vide pendant que celui du fil
porte la requête.
L'invité peut atteindre une seule chose sur votre Mac. Un dossier partagé est
une fenêtre vivante, en lecture-écriture, sur votre vrai système de fichiers, et
l'effacement pour compromission le laisse intact par conception. Partagez le
répertoire du projet plutôt que votre répertoire home, et le find de
l'auxiliaire pour les *.pem parcourt un home Linux plein de checkouts et de
caches de paquets au lieu de vos connexions adossées au trousseau.
La frontière qui n'est pas une étape de la séquence
Lisez ensemble les quatre détails de calendrier de GitSpawn — avant l'invite de
confiance, avant l'authentification, avant la première frappe, avant tout tour
de modèle — et ils disent une seule chose. Chaque protection est une étape d'une
séquence de démarrage, et chaque nouvelle fonctionnalité ajoute une étape devant
elle. Cursor l'a appris en 2025 avec un mcp.json fourni par le dépôt, et de
nouveau en juillet dernier avec une commande de mise en place de worktree qui
s'exécutait avant sa propre invite de
confiance. C'est maintenant le tour de git,
dans sept produits à la fois, via une clé de configuration présente dans git
depuis des années.
Un hyperviseur n'est pas une étape de cette séquence. Il ne lit pas le
.git/config. Aucune refactorisation ne le réordonne et aucun chemin de code ne
s'en exempte, parce qu'il ne s'exécute pas dans le même programme que l'invite.
La VM tournait avant que le zip ait fini de se télécharger, et ses deux
garanties — aucun vrai secret ici et aucune route non médiée vers l'extérieur —
tiennent aussi bien en 2.1.193 qu'en 2.1.196.
Vérifiez votre .git/config avant d'ouvrir un dossier que quelqu'un vous a
envoyé. Manifold a raison de le dire. Vous le ferez aussi pendant deux semaines
puis vous sauterez l'étape au troisième zip d'un après-midi chargé, ce qui est
la durée de vie de la plupart des instructions qui se terminent par « avant de
l'ouvrir ».
Installez Bromure Agentic Coding, donnez au dossier
inconnu sa propre machine, et laissez la config exécuter ce qu'elle veut dans
une pièce où s'exécuter est tout ce qu'elle pourra faire.