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
+19 -4
View File
@@ -868,11 +868,16 @@ keinem anderen Job abgewartet: Er kann weder Bau noch Tests noch die Veröffentl
- Die Quellprüfungen (Abhängigkeiten, Semgrep, Trivy) lesen einen Export des eingecheckten Stands (`git archive HEAD`),
gitleaks liest die Git-Geschichte. Nicht eingecheckte Dateien eines Arbeitsordners erreichen nie ein Werkzeug.
- Die Werkzeuge sind auf feste Fassungen festgelegt (gitleaks, Trivy, osv-scanner, Semgrep, pnpm). Die geladenen
Programme werden vor jeder Benutzung gegen eine SHA256-Prüfsumme im Skript geprüft; bei einer abweichenden Summe oder
- Die Werkzeuge sind auf feste Fassungen festgelegt (gitleaks, Trivy, osv-scanner, Semgrep, pnpm). Semgrep läuft als
Container aus dem offiziellen Abbild, angepinnt über seinen Digest (Docker prüft beim Laden, dass der Inhalt dazu passt);
eine Installation über PyPI gibt es nicht mehr. Die übrigen geladenen Programme werden vor jeder Benutzung gegen eine SHA256-Prüfsumme im Skript geprüft; bei einer abweichenden Summe oder
fehlendem Netz wird nur dieses Werkzeug übersprungen. **Eine Fassung anheben:** im Kopf des Skripts Version, Adresse und
Prüfsumme zusammen austauschen (die Summe stammt aus der offiziellen Prüfsummendatei der Veröffentlichung) und einmal
lokal `sh .gitea/scripts/security-scan.sh all` laufen lassen.
- Das Skript hält ein Zeitbudget von 25 Minuten ein (der Job hat 30): Jedes Werkzeug hat ein eigenes Zeitlimit, und jede
Ergebniszeile wird ausgegeben, sobald das Werkzeug fertig ist – ein Abbruch des Jobs verschluckt also nichts. Wird ein
Limit gerissen, steht `skipped reason=zeitgrenze`, ist das Gesamtbudget aufgebraucht `gesamtbudget`. Prüft das Skript in
einem flachen Klon, meldet gitleaks `unvollstaendig (flacher Klon ...)` statt eines scheinbar sauberen Ergebnisses.
- Das Ergebnis erscheint im Protokoll des Laufs als Zeilen `SECURITY-SUMMARY ...` (nur Zahlen) und, soweit der Runner es
zulässt, als Download `sicherheitsberichte`. Einzelheiten und Fehlersuche stehen im
[CI/CD-Runbook](ci-cd-setup.md).
@@ -965,7 +970,11 @@ Beweis, dass dabei kein POST entsteht, wurde vor dem ersten Lauf gegen einen lok
einmal doch nach einer Anmeldung (die Vorabprüfung meldet dann Status 401), legen Sie eine Datei **außerhalb des
Repositorys** mit einer Zeile `benutzer:passwort` an und rufen das Skript mit `ZAP_BASIC_AUTH_FILE=Pfad` auf. Der Kopf
gelangt über eine temporäre Datei mit Modus 0600 (wird beim Beenden entfernt) in den Container und nie auf eine Befehlszeile
oder in eine Ausgabe. Achtung: Der Bericht enthält dann die gesendeten Kopfzeilen und damit die Zugangsdaten; geben Sie ihn
oder in eine Ausgabe; Sonderzeichen wie `"` oder `\` im Passwort sind erlaubt, weil die Zugangsdaten nur als base64-Text
weitergereicht werden. Der Haken schickt den Kopf **nur an das Ziel** (`ZAP_TARGET`), nie an andere Adressen (Weiterleitungen,
fremde Seiten, Dienste von ZAP selbst). Der Berichtsordner hat Modus 700 (nur der ZAP-Benutzer mit Kennung 1000 schreibt, kein
anderer Benutzer des Rechners liest); hat Ihr Konto nicht die Kennung 1000, übergibt das Skript den Ordner für die Dauer des
Laufs an diese Kennung und danach wieder an Sie zurück. Achtung: Der Bericht enthält dann die gesendeten Kopfzeilen und damit die Zugangsdaten; geben Sie ihn
nicht weiter. Der Ordner `security-reports/` ist von Git ausgeschlossen.
## Konventionen und Fallstricke
@@ -984,7 +993,13 @@ ein Paket, das nur unter `devDependencies` steht, scheitert das erst im Containe
laufen mit allen Abhängigkeiten und fangen es nicht. Dann gehört das Paket in `dependencies`.
**Beweis nach jeder Änderung an den Abbildern:** ein Start gegen eine frische, leere Datenbank (alle
Migrationen laufen, die Zeile „Tessera API running“ erscheint) plus die Rauchtests am neu gebauten
Stack – so wie es `checks/fresh-db-start.sh` im Auftrag quick-261009-p0m vormacht.
Stack. Die Startprobe liegt versioniert im Repository: `bash .gitea/scripts/image-start-check.sh [Abbild]`
(ohne Angabe: `tessera-ctl-api:latest`). Sie startet eine kurzlebige Testdatenbank und das Abbild in einem eigenen Docker-Netz,
wartet auf „Tessera API running“, prüft, dass die Migrationen angewendet wurden, und räumt alles auf; Erfolg heißt Ausgabe
„frische-datenbank ok“ und Exit 0. Die Pipeline ruft sie nicht auf, sie gehört in die Freigabe-Checkliste (Betriebsanleitung,
Kapitel 9). **Der Bau scheitert ausdrücklich**, wenn der Prisma-Client nicht erzeugt werden konnte (eigener Schritt
`prisma generate` mit Prüfung in der Stufe `prod-deps`, denn der `postinstall` verschluckt Fehler) oder wenn npm, npx, corepack
oder yarn im Laufzeitabbild geblieben sind (Platzhalter statt fester Versionspfade, danach eine Prüfung).
**Schutz-Kopfzeilen der Weboberfläche (quick-261009-p0m):** `apps/web/next.config.ts` sendet für
alle Pfade `X-Content-Type-Options`, `Referrer-Policy`, `X-Frame-Options: SAMEORIGIN`, eine