flawopen.com/Teardowns/cve-2026-102437-deepseek-reasonix-git-filter-command-injection
CVE-2026-102437 : injection Git dans les diffs Reasonix
Un duo .gitattributes/.git/config piégé peut lancer un filtre clean à l’affichage d’un diff Reasonix. Mettez npm à 1.39.3 ou Studio à 2.21.0.[1], [2], [3], [6], [7]
Imaginez une table de tri qui promet de comparer uniquement deux étiquettes. Un colis peut contenir une consigne d’acheminement demandant à la table de lancer un auxiliaire enregistré avant de comparer le contenu. Reasonix désactivait certains auxiliaires Git, mais le filtre clean appliqué par fichier constituait une autre voie. Lorsque l’écran de diff demandait à Git de préparer le fichier, ce filtre pouvait s’exécuter avec les droits du développeur.[1], [3]
Concepts Clés et Termes
Filtre clean Git- Transformation configurée que Git peut exécuter pour convertir le contenu d’un fichier de l’arbre de travail vers sa forme stockée dans le dépôt.[1], [3]
.gitattributes- Fichier suivi par le dépôt qui peut associer un filtre nommé à certains chemins.[1]
.git/config- Configuration locale du dépôt pouvant définir la commande appelée par un filtre. Un clone classique ne copie pas ce fichier local.[1], [3]
Visionneuse de diff- Fonction qui demande à Git de préparer et comparer le contenu de travail d’un fichier avec son contenu validé.[1]
Correspondances de référentiels
- Référence CWE pour la faiblesse décrite dans ce guide : CWE-78
Analyse de Cause Racine
Reasonix renforçait les appels git diff avec --no-ext-diff et --no-textconv , mais ces options contrôlent les mécanismes de diff externe et de conversion de texte ; elles ne désactivent pas les filtres de contenu clean de Git. La vue des changements de l’espace de travail appelait git diff pour un chemin sélectionné. Si le contenu du dépôt associait un filtre au chemin via .gitattributes et que la configuration Git locale définissait la commande de ce pilote, Git pouvait l’exécuter lors de la création du blob de comparaison. Le CVE décrit un attaquant local et exige que l’utilisateur ouvre le diff. La publication de GitLab précise qu’un clone normal ne transfère pas .git/config ; une archive, un dossier synchronisé, un cache ou un devcontainer préparé peut le contenir. Elle décrit aussi un agent local disposant des mêmes droits, capable d’écrire cette configuration dans le dépôt. L’impact est l’exécution de commandes avec les droits de l’utilisateur de Reasonix, et non une exécution distante provoquée par la simple ouverture d’un dépôt hébergé sur GitLab.[1], [3]
Déroulement de l'Attaque Étape par Étape
L’espace de travail reçoit un état de dépôt non fiable
Le développeur ouvre un projet dont les attributs suivis associent un fichier à un filtre et dont la configuration Git locale définit ce filtre. L’avis du mainteneur exige ces deux éléments ; un clone normal ne fournit pas, à lui seul, la configuration locale.[1], [3]
Code Source : Vulnérable vs Sécurisé
Ce constructeur d’arguments est illustratif et ne constitue pas un correctif prêt à l’emploi. L’appelant doit énumérer tous les drivers sélectionnés par .gitattributes, .git/info/attributes et les fichiers d’attributs globaux/système, puis ne définir discoveryComplete qu’après une analyse complète réussie. Cette fonction valide les noms fournis et génère des substitutions de configuration en ligne de commande ; elle ne découvre ni ne vérifie l’ensemble des drivers. L’appel vulnérable est cité dans la divulgation de GitLab ; le modèle défensif synthétise les recommandations des mainteneurs et leurs PR de durcissement fusionnées.[1], [3], [4], [5]
Extrait source: desktop/workspace_changes.go
// Appel source cité par GitLab Threat Research ; il s’agit du site d’appel, pas d’une fonction complète.
args := []string{"-C", base, "diff", "--no-ext-diff", "--no-textconv", "--relative", "HEAD", "--", filepath.FromSlash(rel)}
// Constructeur Go d’arguments donné à titre d’illustration, pas un correctif fournisseur reproduit à l’identique.
package gitguard
import (
"errors"
"fmt"
"path/filepath"
"regexp"
)
// L’appelant doit découvrir tous les filtres sélectionnés par les attributs effectifs et transmettre l’ensemble complet.
// Cet utilitaire ne fait que neutraliser ces clés de driver dans toutes les portées de configuration Git.
var filterDriverName = regexp.MustCompile(`^[A-Za-z0-9_-]{1,64}$`)
func hardenedDiffArgs(base, rel string, drivers []string, discoveryComplete bool) ([]string, error) {
if !discoveryComplete {
return nil, errors.New("cannot safely diff: filter-driver discovery failed")
}
args := []string{"-C", base}
seen := map[string]struct{}{}
for _, driver := range drivers {
if !filterDriverName.MatchString(driver) {
return nil, fmt.Errorf("cannot safely diff: unsupported Git filter driver name %q", driver)
}
// Les noms de sous-section de Git config sont sensibles à la casse : ne normalisez pas les noms de driver.
key := driver
if _, ok := seen[key]; ok {
continue
}
seen[key] = struct{}{}
for _, setting := range []string{"clean", "smudge", "process", "required"} {
args = append(args, "-c", "filter."+driver+"."+setting+"=")
}
}
return append(args, "diff", "--no-ext-diff", "--no-textconv", "--relative", "HEAD", "--", filepath.FromSlash(rel)), nil
}
Liste de Contrôle de Sécurité pour l'Ingénierie
- ✓✓ Mettez à jour le paquet npm Reasonix vers la version 1.39.3 ou ultérieure, ou Reasonix Studio vers la version 2.21.0 ou ultérieure, selon les consignes actuelles du projet.[2], [6], [7]
- ✓✓ Lorsqu’un outil lance Git dans un espace de travail contrôlé par l’utilisateur, considérez la configuration locale et les attributs suivis du dépôt comme non fiables.[1], [3]
- ✓✓ Pour chaque appel Git de l’hôte qui transforme du contenu, identifiez les filtres sélectionnés par
.gitattributes,.git/info/attributeset les fichiers d’attributs globaux ou système ; neutralisez leurs clés dans les configurations système, globale, locale et worktree ; échouez de manière sûre si la détection est incomplète.[1], [3], [4], [5] - ✓✓ Conservez
--no-ext-diffet--no-textconvcomme contrôles distincts ; aucun ne remplace la neutralisation des pilotes de filtre.[1] - ✓✓ Ajoutez des tests de régression avec Git réel prouvant qu’un filtre hostile configuré par le dépôt n’est pas exécuté par diff, status, staging, checkout ni les autres opérations de contenu prises en charge par le wrapper.[4], [5]
- ✓✓ Vérifiez si les archives, dossiers partagés, caches et devcontainers contiennent un
.git/configfourni localement ; n’affirmez pas qu’un clone classique transporte ce fichier.[1], [3]
Sources
- GitLab Threat Research — DeepSeek-Reasonix vulnerability details and affected call site
- GitLab Advisory Database — CVE-2026-102437
- DeepSeek-Reasonix maintainer advisory — GHSA-grg2-7gc6-36m6
- DeepSeek-Reasonix Studio host Git hardening PR #11110
- DeepSeek-Reasonix 1.x host Git hardening PR #11114
- DeepSeek-Reasonix 1.39.3 release
- DeepSeek-Reasonix Studio 2.21.0 release
- MITRE CWE-78 — Improper Neutralization of Special Elements used in an OS Command