Zero criticals without a decision across all fifty-four targets, every one of them actually measured. What could not be fixed is decided instead: twenty-seven entries, ninety-two CVE ids, each with a reason and a review date that a rule watches. Criterion 2 ends at one rather than zero, because the image that runs nowhere is the rollback target for the one that does, and prefering it unscanned to keep a number clean would be the wrong trade. Criterion 3 lags until the next scan round, since the scanner runs daily and today is the day everything moved. Both are written down as misses rather than redefined into hits. The closing numbers are hand-computed against the live inventory, not read off the dashboard. That is how the six criticals in the new synapse surfaced at all — the pipeline still holds the report for the version we replaced this evening. A runbook goes with it, because the expensive parts of this pass were never trivy: a delivery path that does not report its own halt, a network rule a chart jump outran, and three indentations I assumed instead of measuring.
6.4 KiB
type, area, related
| type | area | related | ||
|---|---|---|---|---|
| wiki-page | admin |
|
Runbook: einen CVE-Durchgang machen
Wie ein Durchgang durch den Schwachstellen-Bestand abläuft, damit der nächste nicht wieder bei der Sortierung anfängt. Aufgeschrieben nach dem ersten vollständigen Durchgang am 2026-08-21 (#0051), 245 CRITICAL am Anfang.
0. Die eine Regel
⚠️ Vor jedem Update das Zielimage scannen. Das ist der Unterschied zwischen „ein Update hilft vermutlich" und einer Zahl. Am 2026-08-21 hat diese eine Gewohnheit drei Updates verhindert, die den Bestand verschlechtert hätten:
| Kandidat | erwartet | gemessen |
|---|---|---|
Wiki.js 2.5 → 2.5.277 |
besser | 12 → 40 CRITICAL |
| Grafana 12 → 13.2.0 | besser | CRITICAL 7 → 0, aber HIGH 70 → 162 |
| cAdvisor v0.49.1 → v0.55.1 | 0 | 5 → 4 |
Der Aufruf, wie ihn die Anlage selbst macht:
docker run --rm -v "$PWD/trivycache:/root/.cache" aquasec/trivy:0.74.0 \
image --scanners vuln --format json --quiet <image> > ziel.json
1. Bestand aufnehmen und in drei Haufen teilen
„Remediation-Pass" ist keine Aufgabe, sondern drei. Die Trennung ist das eigentliche Werkzeug:
| was es ist | welche Arbeit | |
|---|---|---|
| A | CRITICAL mit verfügbarer Fix-Fassung | ein Aktualisierungs-Vorhaben |
| B | CRITICAL ohne Fix-Fassung | je Fall eine Entscheidung |
| C | CRITICAL auf Images, die nirgends laufen | Reichweite, nicht Patchen |
⚠️ Haufen C ist eine Falle. Der Reflex ist, sie zu patchen. Richtig ist zu fragen, warum sie überhaupt geprüft werden. Am 2026-08-21 waren das 62 CRITICAL auf drei Bau-Artefakten — verschwunden, ohne dass ein einziger Fix nötig war, indem die Zielmenge auf Betriebenes eingeengt wurde (ADR-0026).
⚠️ „Behebbar" ist enger, als die Zahl behauptet. Eine Fix-Fassung im Paket heißt nicht, dass es ein Image damit gibt. Draupnir v3.1.0 trägt fünf Befunde mit Fix-Fassung — und v3.1.0 ist die neueste Release. Solche Fälle gehören zu B, obwohl der Scanner sie zu A zählt.
Nützliche Abfragen:
sort_desc(count by (target) (trivy_vuln_info{severity="CRITICAL"}))
count by (quelle) (cve_target_desired)
cve_critical_offen
2. Haufen A: aktualisieren, gestuft
- Den dokumentierten Weg suchen, bevor gesprungen wird. Authentik verlangt die Reihenfolge der Major-Releases, cert-manager „one minor at a time". Beides stand in der Anleitung; beides hätte ein Sprung verletzt.
- Bruchstellen gegen den eigenen Bestand prüfen, nicht fürchten. Am 2026-08-21 waren 5 von 5 gegenstandslos — geprüft in Minuten, gefürchtet hätten sie einen Tag gekostet.
- ⚠️ Prüfen, ob Flux beim Fehlschlag etwas Eigenes tut.
upgrade.remediation.strategysteht per Vorgabe aufrollback, und mitretries > 0ist auch die letzte Rückrollung scharf. Für die Dauer eines gestuften Sprungsretries: 0setzen und danach zurückstellen — sonst rollt Flux mitten in der Treppe zurück und die Stufen zählen nicht mehr. - ⚠️ Nicht auf Vorrat pushen. Liegt die Ausrollstrecke, wendet Flux nach der Erholung nur den letzten Commit an und überspringt Zwischenstufen. Erst ausrollen und prüfen, dann die nächste Stufe pushen (AAR Spiegel-Ausfall).
- ⚠️ Vor einem Chart-Sprung vergleichen, welche internen Ziele sich verschieben — nicht nur, ob die eigenen Anpassungen überleben. Beide Fassungen mit den echten Werten rendern und Dienstnamen, Selektoren und Ports gegeneinanderhalten. Genau das wurde beim ESS-Sprung versäumt und hat die Anmeldung gekostet (AAR MAS/haproxy).
⚠️ Ein schwebender Fassungsbereich ist eine Decke, keine Aktualität.
version: "0.x" sieht aus wie „bleibt aktuell" und hält in Wahrheit unter dem
nächsten Major fest. Am 2026-08-21 waren genau die zwei Releases mit einem
Bereich die zwei, die zurückgefallen waren — alle fest gepinnten waren aktuell,
weil eine feste Nummer sichtbar veraltet.
3. Haufen B: entscheiden, nicht verstecken
Jeder Fall bekommt einen Eintrag in monitoring/cve/entscheidungen.json im
Betriebs-Repo:
{ "ziel": "coturn/coturn:4.17.2", "art": "hingenommen",
"grund": "4.17.2 ist die neueste veroeffentlichte Fassung ...",
"pruefen_am": "2026-11-21", "cves": ["CVE-...", "..."] }
art:hingenommen(es gibt nichts zu tun) odergeplant(die Arbeit steht aus). Eingeplantbekommt ein kurzes Datum.cveseinzeln, nie pauschal je Image — eine Pauschale verschluckt auch jeden neuen Befund an demselben Image. Der Lader weist einen Eintrag ohne Kennungen ab.grundsagt, warum es nichts zu tun gibt, mit der Messung dahinter. „siehe oben" ist keine Begründung; der Test verlangt Substanz.
⚠️ Bewusst keine Trivy-Ignore-Datei. Trivy ließe die Befunde einfach weg —
dann sähe „0 CRITICAL, weil behoben" genauso aus wie „0 CRITICAL, weil
weggeschaut". Entschieden heißt gezählt, nicht versteckt: die Befunde
bleiben in trivy_vuln_info, und cve_critical_offen zählt, was noch niemand
angesehen hat.
4. Abschließen
cve_critical_offenmuss 0 sein.cve_entscheidungen_abgelaufenmuss 0 sein.- Vorher/Nachher mit Datum in den Abschluss, und die Verengung benennen: Dieser Durchgang war CRITICAL-first. HIGH ist kein Vorhaben, sondern eine Kategorie, und bekommt einen eigenen.
- ⚠️ Nach einer Update-Welle hängen die Zahlen bis zu 24 Stunden
hinterher: die Scan-Runde läuft einmal am Tag, die Herleitung stündlich.
Bis dahin melden
cve_targets_orphanedundcve_targets_missing— das ist der Übergang, nicht ein Schaden.
Was diesen Durchgang teuer gemacht hat
Nicht die CVEs. Teuer waren: eine Ausrollstrecke, die ihren Stillstand nicht meldet (#0109), eine Netzregel, die ein Chart-Sprung überholt hat (#0108), und drei Einrückungen, die ich angenommen statt gemessen habe. Wer den nächsten Durchgang macht, verliert die Zeit an derselben Sorte Sache — nicht an Trivy.