Nach acht Sessions, in denen wir Scanner in unsere GitLab-Pipeline eingebaut haben — SAST, Secret Detection, SCA, License Compliance, Container Scanning, DAST — haben wir jetzt ein anderes Problem. Wir haben hunderte von Vulnerability-Findings. In Teil 9 schauen Patrick Steger und ich uns das eingebaute Vulnerability Management von GitLab an: was es liefert, wo es schwächelt und wie man Findings tatsächlich triagiert, ohne den Überblick zu verlieren.
Was GitLabs Vulnerability Management bietet#
GitLab Ultimate bringt ein Vulnerability-Management-Modul mit, das die Findings aller Scanner aggregiert, die wir in die Pipeline eingebaut haben. Es gibt zwei zentrale Views. Das Security Dashboard zeigt die Anzahl der Vulnerabilities und wie sie sich über die Zeit entwickeln. Der Vulnerability Report erlaubt es, einzelne Findings anzuschauen und zu tracken.
Ein wichtiges Detail: Beide Views beziehen sich immer auf den Default Branch. In unserem Projekt ist das master. Vulnerabilities auf Feature Branches sieht man hier nicht — nur was auf dem Default Branch landet, zählt.
In unserem Beispiel-Java-Projekt zeigt der Report 165 Vulnerabilities: 35 critical, 70 high, 48 medium, 11 low und eine unknown. Du kannst nach Tool (SAST, Dependency Scanning, DAST, Container Scanning, Secret Detection) und nach Severity filtern. Öffnest du ein Finding, bekommst du eine ausführliche Beschreibung — etwa ein Container-Scanning-Finding zu einer SSL-Bibliothek oder ein kritisches Secret-Detection-Finding, das die exakte Zeile zeigt, in der ein AWS Access Token im Source Code gelandet ist.
Aus einem Finding kannst du drei Dinge tun, die wirklich zählen: ein Issue im GitLab Issue Tracker erstellen, das Finding als fixed markieren oder es dismissen. Bei einem erneuten Pipeline-Lauf nach einem Fix erkennt GitLab sogar Findings, die von den Scannern nicht mehr gemeldet werden, und markiert sie als potentially fixed — du kannst sie dann als resolved bestätigen.
Die Limitierungen, die du einplanen musst#
Das Tool ist ein guter Startpunkt, aber Patrick listet die Schwächen klar auf — und die sind für jeden ernsthaften Security-Prozess relevant.
Kein Kommentar beim Dismiss. Wenn du ein Finding dismisst, kannst du nicht festhalten, warum. Sechs Monate später weiss niemand mehr, ob es ein False Positive war, ein akzeptiertes Risiko oder ein Fehlklick.
Kein zeitlich begrenztes Dismiss. Du kannst nicht sagen “Risiko akzeptiert für sechs Monate, dann erneut prüfen”. Entweder dismissed oder nicht.
Dismiss unterscheidet nicht zwischen False Positive und akzeptiertem Risiko. Beides landet im selben Topf. Aus Governance-Sicht sind das zwei sehr unterschiedliche Dinge.
Striktes Format für Drittanbieter-Tools. Du kannst andere Scanner integrieren, aber sie müssen Reports in dem Format liefern, das GitLab erwartet. Wir würden uns wünschen, dass das Vulnerability Management flexibel genug ist, mehrere Formate zu verarbeiten — stattdessen müssen sich die Tools anpassen.
Manuelle Einträge sind umständlich. Willst du ein Finding aus einem manuellen Penetration Test eintragen, verlangt GitLab Felder wie eine CVE-ID und eine Identifier-URL — Felder, die es bei einem manuellen Finding schlicht nicht gibt. Workaround: Dummy-Werte eintragen, die dann für immer im Report stehen. Die Informationen, die du anhängen kannst, sind ebenfalls sehr begrenzt.
Findings driften, wenn sich der Source Code ändert. Patrick hat Fälle gesehen, in denen ein bestehendes Finding nach einer Code-Änderung nicht mehr auf die richtige Stelle gezeigt hat.
Triage-Workflow in der Praxis#
In der Demo sind wir den typischen Lifecycle durchgegangen. Die meisten Findings starten als Needs Triage. Eines untersuchen: ist es real, auf Confirmed setzen und ein Issue daraus erstellen, damit ein Entwickler es übernimmt. Issue und Vulnerability sind beidseitig verlinkt — du kannst von Finding zu Issue navigieren und zurück. Ist es nicht real, Dismiss — und akzeptiere, dass du nicht festhalten kannst, warum.
Für einen manuellen Eintrag haben wir “Cross-Site Scripting aus einem Penetration Test” probiert. GitLab hat die Submission verweigert, bis wir Identifier Code und URL ausgefüllt haben. Wir haben Platzhalter eingetragen, erneut submitted und den Report dann nach Tool = “manually added” gefiltert.
Nach einem Batch von Fixes — in unserem Fall ein Spring-Boot-Update von Version 2 auf 2.7.2 mit angepasstem Test-Framework — haben wir die Pipeline neu laufen lassen. Filtert man den Vulnerability Report nach activity = no longer detected, sieht man eine lange Liste von Issues, die die Scanner nicht mehr finden. Wir setzen sie en bloc auf Resolved. Gleiche Schwäche wie beim Dismiss: kein Platz für Kontext.
Issues anzulegen ist auch der praktische Workaround für das fehlende Kommentarfeld. Das Issue gibt dir einen Ort, um aufzuschreiben, was du tatsächlich getan hast — der Vulnerability-Eintrag selbst tut das nicht.
Key Takeaways#
Vulnerability Management gehört zur Pipeline, nicht als Nachgedanke. Sobald fünf oder sechs Scanner auf jedem Commit laufen, brauchst du einen Ort, um ihren Output zu triagieren. Ohne das produzieren die Scanner nur Lärm, auf den niemand reagiert.
Die Default-Branch-only-Sicht ist eine echte Einschränkung. Findings auf Feature Branches tauchen im Dashboard nicht auf. Plane dein Branching-Modell und deine Security-Gates entsprechend.
Dismiss ohne Begründung ist eine Governance-Lücke. False Positive und akzeptiertes Risiko dürfen nicht gleich aussehen. Bis GitLab das fixt: verlinkte Issues nutzen, um die Begründung festzuhalten.
Manuelle Findings verdienen einen First-Class-Workflow. Der aktuelle Pfad zwingt dich, CVE-IDs zu erfinden. Wenn du viel manuelles Pen-Testing machst, plane ein zweites Tool neben GitLab ein.
Re-Runs erkennen “nicht mehr vorhandene” Findings. Nutze den Filter activity = no longer detected nach jedem Fix-Sweep — das ist der schnellste Weg, den Report aufzuräumen und echten Fortschritt zu sehen.
Issues sind der Workaround für alles, was der Report nicht speichern kann. Kommentare, Historie, Attachments, Audit Trail — all das lebt auf dem Issue, nicht auf der Vulnerability. Etabliere die Gewohnheit früh.
