docs(quick-261009-p0m): Review-Befunde im Sicherheitsprotokoll und in den Anleitungen nachgetragen

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-10-09 20:59:12 +02:00
parent bf632d90a5
commit 8a1218af6a
4 changed files with 78 additions and 21 deletions
+42 -12
View File
@@ -274,7 +274,8 @@ nie verzoegert oder verhindert. Er laeuft nur auf `main` und bei Tags `v*`; die
Bedingung steht ausdruecklich am Job, weil ein uebersprungenes `needs` in Gitea nicht
blockiert (sonst liefe er auch nach einem Push auf `live`). Er hat `continue-on-error`,
ein Zeitlimit von 30 Minuten (ein haengender Scan haelt den einzigen Runner nicht fest)
und kein Secret. Alles steckt in einem Skript, das auch lokal laeuft:
und kein Secret. Das Skript haelt sich selbst an ein Zeitbudget von 25 Minuten (siehe
"Zeitbudget" unten). Alles steckt in einem Skript, das auch lokal laeuft:
```bash
GITHUB_REF=refs/heads/main sh .gitea/scripts/security-scan.sh --print-plan # ohne Netz
@@ -293,15 +294,25 @@ temporaeren Ordner, gitleaks nur die Git-Historie. Es wird also genau der eingec
Stand geprueft; nicht eingecheckte Dateien eines Arbeitsordners erreichen nie ein
Werkzeug, einen Bericht oder ein Artefakt.
**Angepinnte Werkzeuge:** gitleaks 8.30.1, Trivy 0.75.0, osv-scanner 2.6.0, Semgrep 1.180.0
(`pipx`), pnpm 9.15.0. Die drei Programme werden von der offiziellen
**Angepinnte Werkzeuge:** gitleaks 8.30.1, Trivy 0.75.0, osv-scanner 2.6.0, Semgrep 1.180.0,
pnpm 9.15.0. Die drei Programme werden von der offiziellen
GitHub-Veroeffentlichung geladen und vor jeder Benutzung gegen eine SHA256-Summe im Skript
geprueft (auch das zwischengespeicherte Archiv); stimmt die Summe nicht oder fehlt das
Netz, wird nur dieses Werkzeug uebersprungen. Marktplatz-Aktionen fuer Scanner werden
Netz, wird nur dieses Werkzeug uebersprungen. **Semgrep** laeuft als Container aus dem
offiziellen Abbild `semgrep/semgrep`, angepinnt per Digest (`SEMGREP_IMAGE` im Skript):
Docker prueft beim Laden, dass der Inhalt zum Digest passt. Es gibt bewusst keine
Installation ueber `pipx`/PyPI mehr -- deren frei aufgeloeste Abhaengigkeiten liefen sonst
in einem Job, der den Docker-Socket des Hosts sieht. Der Quellstand geht per `docker cp`
in den Container und der Bericht per `docker cp` zurueck (kein Ordner-Mount, denn der
Arbeitsordner liegt im Job-Container und nicht auf dem Docker-Rechner). Das Abbild belegt
rund 1,5 GB im Docker-Daemon des Runners und bleibt dort zwischengespeichert; ohne Docker
wird Semgrep mit `kein-docker` uebersprungen. Marktplatz-Aktionen fuer Scanner werden
bewusst nicht benutzt (veraenderliche Etiketten). **Version anheben:** im Kopf von
`security-scan.sh` die Version, die URL und die SHA256-Summe aus der offiziellen
Pruefsummendatei der Veroeffentlichung gemeinsam austauschen und einmal lokal
`sh .gitea/scripts/security-scan.sh all` laufen lassen. Werkzeuge und die Trivy-Datenbank
`sh .gitea/scripts/security-scan.sh all` laufen lassen. Bei Semgrep stattdessen
`SEMGREP_VERSION` und den Digest in `SEMGREP_IMAGE` tauschen (den Digest zeigt
`docker pull semgrep/semgrep:<Version>` in der Zeile `Digest:`). Werkzeuge und die Trivy-Datenbank
liegen im persistenten Zwischenspeicher des Runners (`/opt/hostedtoolcache/tessera-security`);
der Layer-Zwischenspeicher von Trivy wird nach jedem Lauf geloescht, damit die Platte nicht
vollaeuft.
@@ -311,13 +322,30 @@ Zertifikatsmanagers, Schluessel-Ausschnitte in Tests und Notizen) und `.semgrepi
(Tests, Testdaten, Planungsnotizen). Ein neuer Treffer wird nie vorsorglich freigegeben,
sondern erst geprueft.
**Zeitbudget:** Der Job hat 30 Minuten (`timeout-minutes`). Das Skript rechnet mit einem
Gesamtbudget von 1500 Sekunden (25 Minuten) und jedes Werkzeug hat ein eigenes Limit
(Variablen `T_*` im Kopf des Skripts): Laden der drei Programme je 60 s, Semgrep-Abbild laden
150 s, pnpm 45 s, gitleaks 180 s, `pnpm audit` 90 s, osv-scanner 120 s, Semgrep 300 s, Trivy ueber
den Quellstand 180 s, je Abbild 120 s -- zusammen hoechstens 1485 Sekunden. Zusaetzlich kuerzt das
Skript jedes Limit auf die noch verbleibende Gesamtzeit; ist nichts mehr uebrig, werden die
restlichen Werkzeuge mit `skipped reason=gesamtbudget` gemeldet. Ein Werkzeug, das sein
Limit reisst, erscheint als `skipped reason=zeitgrenze`. Die fuenf Minuten Reserve bis zu den
30 Minuten decken Checkout und Artefakt-Schritt ab. **Jedes Werkzeug gibt seine Zeile aus,
sobald es fertig ist** -- bricht der Runner den Job trotzdem einmal ab, stehen die bis dahin
fertigen Ergebnisse im Protokoll.
**Wo man das Ergebnis sieht:** Im Protokoll des Jobs stehen je Werkzeug eine Zeile
`SECURITY-SUMMARY ...` (nur Zahlen) und am Ende `SECURITY-SUMMARY fertig (nur Bericht,
Exit 0)`; dieselben Zeilen stehen in `summary.txt`. Die Rohberichte (JSON) haengen,
`SECURITY-SUMMARY ...` (nur Zahlen), die Zeile `SECURITY-SUMMARY dauer=...` und am Ende
`SECURITY-SUMMARY fertig (nur Bericht, Exit 0)`; dieselben Zeilen stehen in `summary.txt`.
Prueft das Skript in einem flachen Klon (ohne volle Historie), steht bei gitleaks
`unvollstaendig (flacher Klon ...)` -- dann ist das Ergebnis nicht "sauber", sondern nur fuer die sichtbaren
Commits gueltig (die Pipeline holt mit `fetch-depth: 0` immer die volle Historie). Die Rohberichte (JSON) haengen,
soweit der Runner es zulaesst, als Artefakt `sicherheitsberichte` (30 Tage) am Lauf. Das
Artefakt ist nur "best effort" (Gitea lehnt `upload-artifact@v4` ab, es laeuft `@v3`);
verlassen Sie sich auf die Zeilen im Protokoll. Der Job braucht ungefaehr fuenf bis acht
Minuten nach `publish`.
verlassen Sie sich auf die Zeilen im Protokoll. Der Job braucht auf dem
Entwicklungsrechner mit warmem Zwischenspeicher etwa eine Minute; beim allerersten Lauf auf einem
frischen Runner kommen das Laden der Programme und des Semgrep-Abbilds (rund 1,5 GB) und die
Trivy-Datenbank dazu. Mehr als 25 Minuten laufen nie (siehe "Zeitbudget").
## 5. Sicherheitshinweise
@@ -483,8 +511,10 @@ erst nach `publish` und steht in keinem `needs`). Rot oder gelb heisst deshalb n
etwas nicht ausgeliefert wurde. Zur Ursache im Job-Protokoll die Zeilen
`SECURITY-SUMMARY <werkzeug> skipped reason=...` lesen: `download` oder `checksum` (Werkzeug
nicht ladbar bzw. Summe stimmt nicht -- Netz pruefen, nie die Summe ohne Pruefung
austauschen), `kein-pipx` / `install` (Semgrep), `kein-pnpm`, `abbild-fehlt` (das Abbild
liegt nicht im Docker-Daemon des Hosts), `fehler` (Werkzeug ist abgestuerzt oder hat
nichts geschrieben, z. B. Zeitlimit), `kein-bericht`. Ein haengender Lauf endet nach 30
austauschen), `kein-docker` / `install` (Semgrep: Docker fehlt bzw. das Abbild liess sich nicht
laden), `kein-pnpm`, `abbild-fehlt` (das Abbild
liegt nicht im Docker-Daemon des Hosts), `zeitgrenze` (das Werkzeug hat sein eigenes Limit
gerissen), `gesamtbudget` (die 25 Minuten waren aufgebraucht), `fehler` (Werkzeug ist
abgestuerzt oder hat nichts geschrieben), `kein-bericht`. Ein haengender Lauf endet nach 30
Minuten von selbst. Fehlt nur das Artefakt, ist das erwartbar (best effort); die Zahlen
stehen trotzdem im Protokoll.