No description
  • Python 96.8%
  • Shell 3.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-23 07:47:13 +02:00
cvecheck init 2026-10-23 07:47:13 +02:00
cvecheck.py init 2026-10-23 07:47:13 +02:00
README.md init 2026-10-23 07:47:13 +02:00

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_api bzw. 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.