FlawOpen

flawopen.com/Teardowns/cve-2026-102437-deepseek-reasonix-git-filter-command-injection

● CVE-2026-102437 · CVSS 7.8[2] · Hoch
Sicherheitsforschung · FlawOpen

CVE-2026-102437: Git-Injection beim Reasonix-Diff

Ein manipuliertes .gitattributes/.git/config-Paar startet beim Reasonix-Diff einen clean-Filter. Aktualisiere npm auf 1.39.3 oder Studio auf 2.21.0.[1], [2], [3], [6], [7]

💡 Einfache Erklärung (ELI5)

Stellen Sie sich einen Sortiertisch vor, der verspricht, nur zwei Etiketten zu vergleichen. Ein Paket kann einen Laufzettel enthalten, der den Tisch anweist, vor dem Vergleich einen registrierten Helfer auszuführen. Reasonix deaktivierte einige Git-Helfer, doch der dateibezogene Clean-Filter war ein eigener Pfad. Wenn die Diff-Ansicht Git aufforderte, die Datei für den Vergleich vorzubereiten, konnte dieser Filter mit den Rechten des Entwicklers laufen.[1], [3]

Kernkonzepte & Begriffe

Git-Clean-Filter
Eine konfigurierte Umwandlung, die Git ausführen kann, um Dateiinhalt aus dem Arbeitsverzeichnis in die gespeicherte Repository-Form zu überführen.[1], [3]
.gitattributes
Eine versionierte Repository-Datei, die bestimmten Pfaden einen benannten Filter zuordnen kann.[1]
.git/config
Lokale Git-Konfiguration des Repositorys, die den von einem Filter aufgerufenen Befehl festlegen kann. Ein normaler Clone kopiert diese lokale Datei nicht.[1], [3]
Diff-Ansicht
Eine Funktion, die Git auffordert, den Arbeitsstand einer Datei vorzubereiten und mit dem bestätigten Inhalt zu vergleichen.[1]

Framework-Zuordnungen

  • CWE-Referenz für die in diesem Leitfaden beschriebene Schwachstelle: CWE-78

Ursachenanalyse

Reasonix härtete git diff -Aufrufe mit --no-ext-diff und --no-textconv . Diese Optionen steuern jedoch externe Diff- und Textkonvertierungsmechanismen; Git-Clean-Filter werden dadurch nicht deaktiviert. Die Workspace-Änderungsansicht rief git diff für einen ausgewählten Pfad auf. Wenn Repository-Inhalte dem Pfad über .gitattributes einen Filter zuordneten und die lokale Git-Konfiguration den Befehl dieses Treibers definierte, konnte Git ihn beim Erzeugen des Vergleichsblobs starten. Das CVE beschreibt einen lokalen Angreifer und setzt voraus, dass der Nutzer den Diff öffnet. Laut GitLabs Veröffentlichung überträgt ein normaler Clone .git/config nicht; Archive, synchronisierte Ordner, Caches oder vorbereitete Devcontainer können die Datei enthalten. Außerdem beschreibt sie einen lokalen Agenten mit denselben Rechten, der die lokale Repository-Konfiguration schreiben kann. Die Auswirkung ist Befehlsausführung mit den Rechten des Reasonix-Nutzers, keine Remote-Codeausführung allein durch das Öffnen eines bei GitLab gehosteten Repositorys.[1], [3]

Schritt-für-Schritt Angriffsablauf

Schritt 1

Der Workspace erhält nicht vertrauenswürdigen Repository-Zustand

Der Entwickler öffnet ein Projekt, dessen versionierte Attribute einer Datei einen Filter zuordnen und dessen lokale Git-Konfiguration diesen Filter definiert. Der Maintainer-Hinweis verlangt beide Bestandteile; ein normaler Clone allein liefert die lokale Konfiguration nicht.[1], [3]

Schritt 2

Der Entwickler fordert einen Diff an

Die Änderungsansicht von Reasonix führt den Git-Diff-Pfad für die ausgewählte Datei aus. Diese UI-Aktion ist die vom CVE verlangte Nutzerinteraktion.[1], [3]

Schritt 3

Git wendet den Clean-Filter an

Git bereitet Inhalte für den Vergleich vor und kann den konfigurierten Clean-Filter aufrufen. --no-ext-diff und --no-textconv deaktivieren andere Mechanismen und unterdrücken diesen Filter nicht.[1], [3]

Schritt 4

Der Filter läuft mit den Rechten des Nutzers

Der konfigurierte Filterbefehl läuft im Kontext des Reasonix-Prozesses. Die dokumentierte Folge ist lokale Befehlsausführung mit den Rechten dieses Nutzers.[1], [2], [3]

Quellcode: Verwundbar vs. Sicher

Dieser Argument-Builder dient als Beispiel und ist kein direkt einsetzbarer Patch. Der Aufrufer muss alle durch .gitattributes, .git/info/attributes und globale/System-Attributdateien ausgewählten Driver ermitteln und discoveryComplete erst nach einer erfolgreich abgeschlossenen vollständigen Suche setzen. Diese Funktion prüft die übergebenen Namen und erzeugt Konfigurationsüberschreibungen auf der Kommandozeile; sie ermittelt oder überprüft die Driver-Menge nicht. Der verwundbare Aufruf stammt aus GitLabs Offenlegung; das Abwehrmuster fasst Hinweise der Maintainer und ihre zusammengeführten Hardening-PRs eigenständig zusammen.[1], [3], [4], [5]

Quelltextauszug: desktop/workspace_changes.go

VERWUNDBARE IMPLEMENTIERUNG
// Von GitLab Threat Research zitierter Quellaufruf; dies ist die Aufrufstelle, keine vollständige Funktion.
args := []string{"-C", base, "diff", "--no-ext-diff", "--no-textconv", "--relative", "HEAD", "--", filepath.FromSlash(rel)}
GEHÄRTETER SICHERHEITS-PATCH
// Veranschaulichender Go-Argument-Builder, kein wörtlicher Hersteller-Patch.
package gitguard

import (
    "errors"
    "fmt"
    "path/filepath"
    "regexp"
)

// Der Aufrufer muss alle durch effektive Attribute ausgewählten Filter ermitteln und die vollständige Menge übergeben.
// Dieser Helfer neutralisiert nur diese Driver-Schlüssel in allen Git-Konfigurationsbereichen.
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)
        }
        // Git-config-Unterabschnittsnamen unterscheiden Groß- und Kleinschreibung: Driver-Namen nicht vereinheitlichen.
        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
}

Checkliste für Engineering & Systemsicherheit

Quellen