- Python 96.8%
- Shell 3.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| cvecheck | ||
| cvecheck.py | ||
| README.md | ||
cvecheck
Scannt alle (sichtbaren) GitLab-Projekte auf betroffene Pakete für eine Liste gegebener CVEs. Abhängigkeiten werden aus Manifesten, Lockfiles und Build-/CI-Dateien extrahiert und die gepinnten Versionen mit den verwundbaren Versionenbereichen verglichen.
Voraussetzungen
- Python 3 (nur Standardbibliothek – keine Pakete zu installieren)
- Ein GitLab-API-Token mit Lesezugriff (
read_apibzw.read_repository) - Erreichbarkeit von OSV.dev und cve.org (für die CVE-Auflösung)
Nutzung
Das Wrapper-Skript cvecheck führt cvecheck.py aus:
# Einzelne CVE, Token aus Datei
./cvecheck -u https://git.chefkoch.net -t "$(cat token)" --cves CVE-2026-114406
# Mehrere CVEs + archivierter Projekte ausschließen
./cvecheck -u https://git.chefkoch.net -t "$(cat token)" --exclude-archived --cves CVE-1,CVE-2,CVE-3
# Liste aus Datei (eine ID pro Zeile), nur bestimmte Projekt-Prefixe, JSON-Ausgabe
./cvecheck -u https://git.chefkoch.net -t mytoken --cve-file cves.txt --only team-a/ --json -o findings.json
Optionen
| Option | Bedeutung |
|---|---|
-u, --url URL |
GitLab-Basis-URL (erforderlich; alternativ Umgebungsvariable GITLAB_URL; fehlt das Schema, wird https:// ergänzt) |
-t, --token TOKEN |
API-Token (alternativ Umgebungsvariable GITLAB_API_TOKEN; erforderlich) |
--cves LISTE |
Komma-getrennte CVE-IDs, wiederholbar; CVEs werden normalisiert (CVE-* großgeschrieben) |
-f, --cve-file DATEI |
Datei mit einer CVE-ID pro Zeile (kombinierbar mit --cves) |
--only PREFIX |
nur Projekte scannen, deren Pfad mit PREFIX beginnt (wiederholbar) |
-j, --jobs N |
parallele Worker pro Projekt (default 8) |
--json |
maschinenlesbares JSON auf stdout (und in die Output-Datei) |
--exclude-archived |
archivierte Projekte ausschließen (Standard: alle sichtbaren Projekte) |
-o, --output-file DATEI |
Findings zusätzlich in diese Datei schreiben (default: findings.txt) |
--no-output |
keine Findings-Datei schreiben |
Umgebungsvariablen
| Variable | Bedeutung |
|---|---|
GITLAB_URL |
GitLab-Basis-URL, falls -u nicht angegeben wird |
GITLAB_API_TOKEN |
Token, falls -t nicht angegeben wird |
OSV_API_URL |
OSV-API für Tests gegen einen Mock |
CVEORG_API_URL |
CVE-Services-API für Tests gegen einen Mock |
Exit-Codes
0– keine betroffene Stelle gefunden (oder keine Treffer)2– mindestens eine Stelle ist betroffen (BETROFFEN)1– Fehler (fehlender Token, API-Fehler, …)
Die Ausgabe enthält pro Projekt die einzelnen Stellen mit Datei:Zeile, Status (BETROFFEN, NICHT betroffen, unbestimmt (keine exakte Pin)), CVE-ID, Paket, Ökosystem und Version. Am Ende steht eine Zusammenfassung („Projekte mit Treffern … betroffene Stellen …“).
Funktionsweise
Zuerst werden die CVEs aufgelöst: Primärquelle ist OSV.dev (/v1/vulns/<id> inkl. Alias-Auflösung), da es strukturierte Paket-/Versionsdaten liefert. Zusätzlich wird bei jeder CVE der Record aus der cve.org-Datenbank (CVE Services API) konsultiert und sein Datenbestand mit den OSV-Ergebnissen zusammengeführt (Union), damit keine betroffene Paket-/Ökosystem-Kombination verloren geht, auch wenn eine der Quellen lückenhaft ist: Advisory-Referenzen aus den References des Records (z. B. zu GHSA-/PYSEC/OSV-IDs) werden erneut über OSV.dev aufgelöst, und die affected[]-Einträge von cve.org werden in ein OSV-kompatibles Format synthetisiert – dabei wird das Ökosystem aus versionType/vendor/product abgeleitet (rpm → RedHat, deb → Debian, apk → Alpine), Image-/Pfadnamen werden verworfen und Einträge ohne Versionen mit Status „affected“ bedeuten „alle Versionen betroffen“. Anschließend listet cvecheck alle sichtbaren GitLab-Projekte auf (optional ohne archivierte) und holt pro Projekt die Dateibaum-Liste; Kandidaten-Dateien – requirements*.txt, Pipfile, pyproject.toml, package.json/Lockfiles, go.mod, pom.xml, Gemfile(.lock), GitHub-Workflow-YAMLs sowie Docker-/Containerfiles und .gitlab-ci.yml (max. 120 Dateien pro Projekt) – werden parallel (-j) geladen und mit Ökosystem-spezifischen Extraktoren ausgewertet: npm-/PyPI-Pins inkl. Lockfile-Auflösung, Go/Maven/Ruby-Gemfiles, GitHub-Actions-Versionen sowie apt/apk/dnf-Installationszeilen in Build- und CI-Dateien. Versionen werden exakt oder über die OSV-Bereiche (introduced/fixed) abgeglichen; eine nicht gepinnte Abhängigkeit wird nur dann als betroffen eingestuft, wenn laut CVE-Daten alle Versionen verwundbar sind (offenes Intervall ab 0). Bei OS-Paketen greift zusätzlich ein Distro-Kompatibilitätsfilter auf zwei Ebenen, um Cross-Distro-Fehlalarme zu vermeiden: pro Datei muss das Base-Image zur Paketfamilie passen (RPM → RHEL/UBI/CentOS/Fedora, apt → Debian/Ubuntu, apk → Alpine; bekannte Official Images wie node:*, golang:*, python:*, ruby:* werden als Debian-basiert erkannt, und Install-Befehle – apk add, apt-get install, dnf/yum/rpm – verraten die Distro auch bei nicht klassifizierbaren Image-Namen wie internen Registry-Images oder Jinja-Variablen); pro Zeile in Multi-Distro-Files (z. B. Molecule-Templates mit apt/dnf/apk-Fallback-Ketten) wird eine Installationszeile nur dann gegen einen CVE-Eintrag geprüft, wenn ihr Paketmanager zur Familie des Eintrags passt. Ist weder Base-Image noch Befehl erkennbar, wird konservativ gemeldet. Die Findings werden pro Projekt dedupliziert und in Text- oder JSON-Form nach stdout sowie standardmäßig nach findings.txt geschrieben.