flawopen.com/Incidents/gitlab-commits-api-path-traversal-september-2026
CVE-2026-85706: GitLab-Dateioffenlegung
GitLabs Upload-Parser konnte ohne Anmeldung Serverdateien auswählen; fehlerhafte Escapes zeigten Fragmente in Fehlermeldungen.[1], [3]
Stellen Sie sich einen Empfangsmitarbeiter vor, der statt des Dokuments im Eingangsfach eine vom Besucher notierte Schranknummer annimmt. Noch vor der Ausweiskontrolle öffnet er den Schrank. Kann er eine Zeile nicht lesen, zitiert er sie laut in der Fehlermeldung. Das Öffnen ist ein Fehler, das Vorlesen ein zweiter.[1]
Kernkonzepte & Begriffe
Upload metadata- Vom Client gelieferte file.path- oder metadata.path-Werte dürfen einen vom vertrauenswürdigen Upload-System registrierten Puffer nicht ersetzen.[1]
Percent decoding- Bei Formulardaten wird % mit zwei Hexadezimalziffern dekodiert; eine ungültige Folge kann einen Fehler mit dem betroffenen Fragment erzeugen.[1]
CWE-22 / CVSS- Die CNA stuft
CVE-2026-85706als Pfad-Traversal mit CVSS 10.0 Kritisch ein. Überschritten wird die Grenze zur clientgesteuerten Auswahl von Serverdateien.[3]
Framework-Zuordnungen
- CWE-Referenz für die in diesem Leitfaden beschriebene Schwachstelle: CWE-22
- CISA KEV — aufgenommen am 2026-09-11 — CVE-2026-85706
Vorfall-Zeitstrahl
GitLab veröffentlichte die Korrekturen 19.1.8, 19.2.6 und 19.3.2.[2]
Die Versionsmitteilung ergänzte Rückportierungen für 18.11.12 und 19.0.9.[2]
Schritt-für-Schritt Angriffsablauf
Auswahl vor Anmeldung
Upload-Metadaten konnten den erwarteten temporären Puffer noch vor der Authentifizierung durch einen Serverpfad ersetzen.[1]
Datei als Formular behandelt
Bei application/x-www-form-urlencoded wurde die ausgewählte Datei als Formulardaten verarbeitet, statt als normale Commit-Antwort zurückgegeben zu werden.[1]
Fragment im Fehler
Ungültige Prozentkodierung konnte das fehlerhafte Fragment in eine Fehlermeldung übernehmen. & und = begrenzten dessen Umfang; ein Lesevorgang allein beweist keine Offenlegung.[1]
Untersuchung
Verknüpfen Sie Einträge der Rails-API und von Workhorse über correlation_id; vergleichen Sie api_error mit written_bytes, um festzustellen, ob Antwortdaten gesendet wurden.[1]
Quellcode: Verwundbar vs. Sicher
Anschauliches Python-Modell, weder GitLab-Quellcode noch dessen Patch. Das fehlerhafte Beispiel nutzt nur Speicherpuffer und behandelt jedes % als Fehler; echte Prozentprüfung und Fragmentgrenzen werden nicht nachgebildet. Das verbesserte Modell authentifiziert zuerst, verweigert Pfadmetadaten, nimmt nur Bytes aus dem vertrauenswürdigen Upload-System an, begrenzt die Größe und liefert allgemeine Fehler. Installieren Sie das Herstellerupdate: Prüfung innerhalb einer Route kommt zu spät, wenn frühere Middleware die Datei bereits gelesen hat.[1]
from urllib.parse import unquote_to_bytes
def parse_upload(authenticated, metadata, buffers):
# Harmlose In-Memory-Fixtures; kein Dateisystemzugriff.
body = buffers.get(metadata.get("path"), b"")
if b"%" in body:
return 400, body.decode("ascii", errors="replace")
if not authenticated:
return 401, "Unauthorized"
return 200, unquote_to_bytes(body)
from urllib.parse import unquote_to_bytes
MAX_BYTES = 4096
HEX = frozenset(b"0123456789abcdefABCDEF")
def parse_upload(authenticated, metadata, registered_body):
# registered_body stammt aus vertrauenswürdiger Upload-Middleware,
# niemals aus einem durch Anfrageparameter gewählten Pfad.
if not authenticated:
return 401, "Unauthorized"
if metadata or type(registered_body) is not bytes:
return 400, "Invalid upload"
if len(registered_body) > MAX_BYTES:
return 413, "Upload too large"
for i, byte in enumerate(registered_body):
if byte == 37 and (i + 2 >= len(registered_body) or
registered_body[i+1] not in HEX or
registered_body[i+2] not in HEX):
return 400, "Invalid upload"
return 200, unquote_to_bytes(registered_body)
Checkliste für Engineering & Systemsicherheit
- ✓Aktualisieren Sie auf eine unterstützte korrigierte Version. Untergrenzen je Zweig: 18.11.12, 19.0.9, 19.1.8, 19.2.6 und 19.3.2; betroffen sind Releases ab 18.7. Gleichen Sie die installierte Version mit dem Herstellerhinweis ab.[2], [3]
- ✓Testen Sie anonyme Anfragen mit harmlosen Speichermarkern: kein Pufferzugriff vor der Anmeldung und kein Marker in Antworten oder normalen Logs. Pfadmetadaten vor dem Parsen ablehnen.[1]
- ✓Bewahren Sie die Rails-API- und Workhorse-Logs auf; verknüpfen Sie die Einträge über
correlation_idund vergleichen Sieapi_errormitwritten_bytes. Prüfen Sie dekodierte Werte von file.path und metadata.path, statt ganze Logzeilen wegen eines harmlosen Upload-Pfads zu verwerfen. Ein Lesezugriff beweist keine Offenlegung: Laut GitLab weist ein in api_error reflektierter Ausschnitt, bestätigt durch Workhorse-written_bytes, auf zurückgesendete Bytes hin; der HTTP-Status allein ist kein Beweis.[1] - ✓Rotieren Sie nur Zugangsdaten, die nachweislich oder begründet möglicherweise offengelegt wurden. Falls
db_key_baseoderotp_key_basebetroffen sein könnten, wenden Sie sich vor einer Rotation an den GitLab-Support: GitLab zufolge gibt es derzeit keinen unterstützten Rotationsweg fürdb_key_base; eine nicht unterstützte Schlüsselrotation kann zu Datenverlust führen. Fehlende Logs belegen keine fehlende Offenlegung.[1]