diff --git a/docs/design/2026-08-21-cve-ziele-ableiten.md b/docs/design/2026-08-21-cve-ziele-ableiten.md index cf1f073..117f46a 100644 --- a/docs/design/2026-08-21-cve-ziele-ableiten.md +++ b/docs/design/2026-08-21-cve-ziele-ableiten.md @@ -509,3 +509,93 @@ damit beim Umschalten in Slice 3 kein Neustart-Rennen entsteht. Zahl. `cve_targets_missing` muss **24** ergeben, `cve_targets_orphaned` **2**, `cve_target_coverage_ratio` **≈ 0,52** — die Werte der Handmessung. Weicht sie ab, ist die Herleitung falsch. + +### Slice 2 — durchgeführt, Commit `b989987` · Status: **DONE** + +**Abweichung von Gate 3: vier Regeln statt drei.** Die vierte +(`CveTargetsNoneDesired`) deckt einen Fall ab, den die anderen drei **nicht +sehen**: Alle Quellen antworten sauber, aber leer. Dann ist `missing` 0 (leere +Soll-Menge), die Frische-Stempel sind aktuell — und es wird nichts mehr +gescannt. `test_targets.py` führt genau diesen Fall bereits als *„leere Menge +ist NICHT dasselbe wie Erfolg"*; die Regel gehört dazu. + +**Erste Regeltests in diesem Stack überhaupt** (`prometheus/alerts_test.yml`). +Je Regel ein Fall, in dem sie feuern **muss**, und einer, in dem sie schweigen +**muss** — sonst ließe sich eine Regel, die immer feuert, von einer richtigen +nicht unterscheiden. `promtool check rules`: 20 Regeln, `promtool test rules`: +SUCCESS. + +**Zwei Sabotagen belegen, dass die Tests beißen:** +- Schwelle von `CveTargetSourceStale` auf `999999999` → der erwartete Alarm + bleibt aus, Test rot. +- Karenz `for: 6h` bei `CveTargetsMissing` entfernt → Alarm feuert bei 5 h, wo + der Test Stille verlangt, Test rot. + +Die Karenz ist damit nachweislich tragend und keine Zierde: Eine volle Runde +über ~65 Images dauert, nach einem Ausrollen ist die Lücke vorübergehend echt. + +**Dashboard:** Deckung und ungeprüfte Images in die zwei freien Plätze der +obersten Reihe, Quellen-Frische als Balken **unten** angehängt — kein +bestehendes Panel verschiebt sich. Geprüft: JSON lesbar, IDs eindeutig, keine +doppelt belegte Position. + +### Slice 3 — durchgeführt, Commit `386b65a` · Status: **DONE** + +`images.txt` ist **gelöscht** — Kriterium 1 erfüllt. Der Scanner liest +`/targets/targets.txt`. + +Ohne brauchbare Liste tut die Schleife nichts und versucht es nach **einer +Minute** erneut statt nach 24 Stunden: Nach einem Ausrollen schreibt der +Exporter die Datei erst beim nächsten Scrape. Belegt mit gestelltem Trivy: ohne +Liste ausgesetzt, leere Liste ausgesetzt, mit Liste genau die zwei Einträge +gescannt und die Kopfzeile ignoriert. + +### Slice 4 — durchgeführt, Commit `07875ba` · Status: **DONE** + +Berichte ohne Ziel werden entfernt — **nur** gegen eine erfolgreich gelesene +Liste. Der Fall vom 2026-08-20 (`threadnet-web:v0.3.0` meldet HIGH-CVEs, obwohl +das Image nirgends läuft) ist als eigener Testfall geführt. + +⚠️ **Der Test hat sich erst selbst als wertlos entlarvt.** Die erste Fassung +**baute** die Schleifenlogik nach, statt sie zu prüfen — und wäre grün +geblieben, während die ausgelieferte Datei kaputt ist. Nach dem Umbau auf +*Laden* der echten `runde()` (Ladewache `SCAN_LOOP_NUR_LADEN`) fiel binnen eines +Laufs auf, dass `scan-loop.sh` seine Pfade **fest** setzte und die Umgebung +ignorierte. Ein nachgebauter Test prüft den Nachbau. + +⚠️ **Zwei eigene Fehler, hier behoben:** +1. Der Treiber lautete `runde || sleep A && sleep B`. Das gruppiert + links-assoziativ zu `(runde || sleep A) && sleep B` — bei fehlender Liste + hätte er die Wartezeit **und danach das volle Tagesintervall** geschlafen, + also genau das, was die kurze Wartezeit verhindern soll. +2. Pfade fest verdrahtet, obwohl der Exporter sie längst aus der Umgebung nimmt. + +**Gegenprobe:** Wache entfernt → „Berichte unberührt" fällt von **2 auf 0**, der +gesamte Bestand wäre gelöscht. Der Test fängt es. + +### Übergabe — was der Ausrollende prüfen muss + +Vor der Übergabe belegt (ohne Host): `py_compile` sauber · **21** Python- +Zusicherungen grün · **13** Shell-Zusicherungen grün · `sh -n` beide · +`docker compose config` grün · `promtool check rules` 20 Regeln · +`promtool test rules` SUCCESS. + +⚠️ **`docker compose up -d` genügt nicht** (AAR 2026-08-01, Befund 2): +`--force-recreate` für `cve-exporter` und `cve-scan`, und die Konfiguration +**im Container** prüfen, nicht auf der Platte. + +| # | Prüfung | Erwartet | +|---|---|---| +| 1 | `cve_targets_missing` **vor** der ersten neuen Runde | **24** — die Handmessung | +| 2 | `cve_targets_orphaned` vorher | **2** | +| 3 | `cve_target_coverage_ratio` vorher | **≈ 0,52** | +| 4 | `docker exec cve-scan cat /targets/targets.txt \| wc -l` | ~65 | +| 5 | Nach einer vollen Runde: `missing` / `orphaned` | **0** / **0** | +| 6 | `threadnet-web:v0.6.0` hat einen Bericht | ja | +| 7 | `threadnet-web:v0.3.0` hat **keinen** mehr | ja | +| 8 | Zahl der Meldungen im Security-Raum in der ersten Runde | **gemessen notieren** (erwartet ≤ 65, gestern waren es 12) | +| 9 | Dauer der ersten vollen Runde | **gemessen notieren** | +| 10 | `cve_target_source_stale` je Quelle | < 3600 | + +**Weicht 1–3 ab, ist die Herleitung falsch — nicht die Handmessung überholt.** +Dann nicht weiterfahren, sondern den Unterschied ausmessen. diff --git a/docs/ledger/2026-08-21-cve-ziele-ableiten.md b/docs/ledger/2026-08-21-cve-ziele-ableiten.md index dc5fcd2..28f349c 100644 --- a/docs/ledger/2026-08-21-cve-ziele-ableiten.md +++ b/docs/ledger/2026-08-21-cve-ziele-ableiten.md @@ -23,6 +23,9 @@ related: | slice | commit | status | note | |---|---|---|---| +| 4 | 07875ba | DONE | Berichte ausgefallener Ziele entfernt; Test laedt die echte runde() statt sie nachzubauen. | +| 3 | 386b65a | DONE | Scanner liest die abgeleitete Menge, images.txt geloescht (Kriterium 1). | +| 2 | b989987 | DONE | Vier Regeln statt drei; erste Regeltests im Stack, zwei Sabotagen belegen sie. | | 1 | 27770b6 | DONE_WITH_CONCERNS | Herleitung + Metriken, nur beobachtend; Abnahme (24/2/0,52) erst nach dem Ausrollen messbar. | ## Ladder @@ -73,3 +76,10 @@ von `v0.8.0` statt `v0.10.0`) — der Test korrigierte meinen Denkfehler, nicht den Code. Und der erste Compose-Eingriff ging von falscher Einruckung aus; die `assert`-Zeile davor hat verhindert, dass eine halb angewandte Aenderung geschrieben wurde. Beide Male war die Kontrolle billiger als der Schaden. + +**Der Test von Slice 4 war zuerst wertlos, und das war lehrreich.** Er baute die +Schleifenlogik NACH, statt sie zu laden - und waere gruen geblieben, waehrend +die ausgelieferte Datei kaputt ist. Nach dem Umbau auf Laden der echten +`runde()` fiel binnen eines Laufs auf, dass `scan-loop.sh` seine Pfade fest +setzte und die Umgebung ignorierte. Wer eine Nachbildung prueft, prueft die +Nachbildung.