
Scanner en lecture seule pour les paramètres git qui permettent à un dépôt d'exécuter du code dans des agents de codage (Claude Code, Codex, Cursor, Copilot). Couvre la classe GitSpawn et la CVE-2026-45033. Aucune dépendance, aucun réseau, aucune télémétrie.
Un dépôt qui peut faire exécuter du code à votre agent de codage dès qu'il ouvre le dossier. GuardSkill vérifie cela avant vous.
npx guardskill .
Lecture seule. Aucun appel réseau, aucune télémétrie, aucune configuration, aucun compte. Il lit la configuration git et les scripts de hooks, affiche ce qu'il trouve, puis se termine.
Les agents de codage rassemblent du contexte en exécutant des commandes git ordinaires — git status, git diff — dès qu'ils ouvrent un projet. Git lit ses paramètres depuis le .git/config du dépôt lui-même, et plusieurs de ces paramètres désignent un programme que git doit exécuter. Placez une commande dans core.fsmonitor et elle s'exécute, avec vos privilèges, hors de toute sandbox, avant même que vous ayez tapé quoi que ce soit.
Deux travaux de recherche publics rendent cela concret :
.git/config.git déjà inclus@github/copilot 1.0.43 en forçant safe.bareRepository=explicit. (Avis GitHub)L'atténuation recommandée côté utilisateur dans les deux articles est la même : inspecter la configuration git avant d'ouvrir le répertoire avec un agent. C'est une tâche fastidieuse à faire à la main sur toute une arborescence. Cet outil le fait en une seconde.
GuardSkill parcourt l'arborescence et trouve chaque configuration git qu'un agent pourrait récupérer : le .git du projet lui-même, tout .git imbriqué arrivé comme contenu, tout dépôt nu caché dans un sous-répertoire, le fichier .git laissé par un sous-module ou un worktree lié, et les configurations que git conserve à côté de la principale — config.worktree et chaque .git/modules/<nom>/config. Chacune d'elles est inspectée.
| Classe | Vérifications |
|---|---|
| Clés d'exécution directe | core.fsmonitor, core.sshCommand, core.gitProxy, core.pager, core.editor, sequence.editor, diff.external, uploadpack.packObjectsHook |
| Clés d'exécution indirecte | filter.*.clean / .smudge / .process, diff.*.textconv, merge.*.driver, mergetool.*.cmd, difftool.*.cmd, credential.helper |
| Alias shell | tout alias.* dont la valeur commence par ! |
| Configuration chargée depuis ailleurs | include.path, includeIf.*.path |
| Hooks | les remplacements core.hooksPath, les scripts actifs (non .sample) dans .git/hooks, et les scripts de hooks qui envoient un téléchargement vers un shell ou décodent du base64 avant de l'exécuter |
| Transports | protocol.allow et protocol.<nom>.allow remis à always, et toute URL de remote ou de sous-module utilisant le transport ext::, qui transmet le reste de la ligne à un shell |
| Structure | les dépôts nus dans l'arborescence (le vecteur CVE-2026-45033), les répertoires .git imbriqués qui ne sont pas des sous-modules enregistrés, les fichiers .git pointant vers un répertoire git dans l'arborescence |
npx guardskill . # analyser le projet courant
npx guardskill ~/code/some-project # analyser un chemin spécifique
npx guardskill . --json # lisible par machine
npx guardskill . --out report.md # écrire aussi un rapport Markdown
npx guardskill . --fail-on critical # échouer le build uniquement sur les découvertes critiques
npx guardskill . --exclude test/fixtures # ignorer un répertoire
Codes de sortie : 0 rien au niveau ou au-dessus du seuil, 1 découvertes au niveau ou au-dessus (seuil par défaut : high), 2 l'analyse elle-même a échoué.
En CI :
- name: Check for git execution vectors
run: npx guardskill . --fail-on high
Exemple de sortie :
GuardSkill - git execution-vector scan (read-only)
Path: /Users/dev/projects/inherited-project
Git configurations inspected: 2 Directories walked: 148
[CRITICAL] vendor/payload.git - Bare git repository found inside the project tree
what Git discovers bare repositories while walking directories and applies their
configuration, including keys that execute commands.
found bare repository at vendor/payload.git
do Do not open this project with a coding agent until you have inspected the directory.
[CRITICAL] vendor/payload.git/config:3 - core.fsmonitor runs an external command
found core.fsmonitor = /tmp/.x/run.sh
2 critical, 0 high, 0 medium, 0 low.
Nothing was changed - this scan only reads.
Un outil de sécurité qui crie au loup se fait désinstaller. La suite s'exécute sur 29 dépôts propres réalistes — git-lfs, git-crypt, husky, la convention .githooks, les sous-modules enregistrés, les assistants d'identification, les éditeurs et pagers personnalisés, la configuration de signature — et le build échoue si l'un d'eux produit une découverte au-dessus du niveau informatif. Elle s'exécute sur 22 dépôts construits autour d'un schéma d'attaque connu et échoue si l'un est manqué, ou est détecté par la mauvaise règle.
Par-dessus cela se trouve une suite d'évasion : chaque cas qu'elle contient a été trouvé en attaquant une version de GuardSkill qui passait déjà ses propres tests, et elle s'exécute à chaque commit afin qu'un futur changement ne puisse pas silencieusement en rouvrir un. Elle couvre la même clé orthographiée de toutes les façons que git accepte encore (casse, guillemets, continuations de ligne, CRLF, un marqueur d'ordre d'octets, une clé sur la ligne de section), les charges utiles nommées d'après des outils familiers, les répertoires de hooks nommés .husky pour paraître banals, et les configurations cachées là où la première version n'a jamais regardé. Une suite de robustesse lui fournit des configurations binaires, vides, tronquées et de 200 000 lignes, des répertoires illisibles, des boucles de liens symboliques et des pointeurs dirigés hors de l'arborescence, et exige un rapport plutôt qu'une trace de pile.
Deux choix de conception délibérés :
.githooks sont signalés comme informatifs (low) plutôt que comme un risque — mais GuardSkill lit quand même les scripts, et passe à critical si l'un d'eux récupère ou décode du code avant de l'exécuter.include / includeIf est toujours signalé. Un include peut introduire n'importe quelle clé de cette liste plus tard, ce qui est exactement la façon de cacher une telle clé. Un ~/.gitconfig partagé que vous avez écrit vous-même est une découverte normale à ignorer..husky exécutant npm test est informatif, et la découverte liste ce qui s'exécutera. Le même répertoire exécutant quelque chose depuis /tmp ne l'est pas.Il ne modifie rien, jamais. Il n'exécute rien de ce qu'il trouve. Il ne fait aucun appel réseau et ne collecte aucune télémétrie — exécutez-le hors ligne et il se comporte à l'identique. Il ne scanne pas encore les dépendances npm, .claude/settings.json, .vscode/tasks.json ou les définitions de serveurs MCP ; ce sont la prochaine classe, pas celle-ci. Et c'est un signal, pas un verdict : lisez la découverte, regardez les preuves, décidez par vous-même.
SKILL.md dans ce dépôt permet à un agent de codage d'exécuter lui-même l'analyse avant d'ouvrir un projet inconnu. Copiez le répertoire dans votre dossier de compétences, ou pointez votre agent vers le dépôt.
npm test # régénère les fixtures, puis exécute la suite
Les fixtures sont générées par du code (test/fixtures/generate.js), non commitées à la main, donc étendre l'ensemble propre ou vulnérable est affaire de quelques lignes. Les nouvelles règles de détection vont dans rules/git-exec-keys.json — une règle sans fixture des deux côtés ne sera pas fusionnée.
La surveillance continue, les alertes Slack/Teams et les pull requests de correction automatique sont prévues comme couche payante. Le scanner lui-même reste gratuit et sous licence MIT. Les règles de détection restent dans le dépôt ouvert — un outil de sécurité dont vous ne pouvez pas lire les règles n'est pas un outil auquel vous devriez faire confiance.
MIT. Construit et maintenu par Helios IT Solutions, un fournisseur néerlandais de services informatiques. Problèmes de sécurité : voir SECURITY.md.