ci(quick-261009-p0m): ZAP-Grundpruefung gegen alpha vor Freigaben, erster Lauf

- zap-baseline.sh: passive Aussenpruefung mit festgelegtem ZAP-Abbild, Ziel per ZAP_TARGET (Standard: oeffentliche Adresse von alpha), Anmeldedatei-Weg nur fuer den Ausnahmefall
- zap-hooks.py: Spinne fuellt keine Formulare aus und sendet keine (POST=0 lokal bewiesen)
- Sicherheitsprotokoll: Abschnitt Pruefung von aussen, erster Lauf direkt gegen die Anwendung (0 hoch, 2 mittel, 6 niedrig, 3 Info), Einordnung und Verlauf
- Betriebsanleitung Kapitel 9: Schritt Pruefung von aussen; Entwicklungsanleitung: Abschnitt ZAP; CHANGELOG

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-10-09 19:43:46 +02:00
parent 5b36b9a564
commit 13571df994
6 changed files with 276 additions and 2 deletions
+32
View File
@@ -907,6 +907,38 @@ Code-Analyse). Die Regeln:
- Jeder Eintrag in `.gitleaks.toml` trägt eine deutsche `description`, die sagt, warum es ein Fehlalarm ist.
- Nie ganze Verzeichnisse außerhalb der Ordner mit Testdaten freigeben.
### Prüfung von außen (ZAP)
Vor einer Freigabe wird alpha mit dem OWASP-ZAP-Abbild von außen angesehen (Ablauf: Betriebsanleitung, Kapitel 9, „Eine
Version freigeben“). Vom Hauptordner des Repositorys aus:
```bash
sh .gitea/scripts/zap-baseline.sh --print-plan # zeigt Ziel, Abbild und Aufruf, ohne Netz
sh .gitea/scripts/zap-baseline.sh # Lauf gegen https://alpha.tessera.ctl.de
ZAP_TARGET=http://HOST:3000 sh .gitea/scripts/zap-baseline.sh # direkt gegen die Anwendung, ohne Proxy
```
Umgebungsvariablen: `ZAP_TARGET` (Ziel; Standard ist die öffentliche Adresse von alpha), `ZAP_SPIDER_MINUTES` (Höchstdauer der
Spinne, Standard 3), `ZAP_REPORT_DIR` (Standard `security-reports/zap-{Zeit}`), `ZAP_DOCKER_NETWORK` (optional, Docker-Netz
des Containers) und `ZAP_BASIC_AUTH_FILE` (siehe unten). Ergebnis sind `zap.html`, `zap.md` und `zap.json` im Berichtsordner
sowie die Zeile `ZAP-SUMMARY ziel=… hoch=… mittel=… niedrig=… info=…` mit je einer Zeile `ZAP-MELDUNG` pro Meldungsart. Das
Skript endet mit Exit 0, wenn der Bericht entstanden ist, und mit 3, wenn nicht; so bemerkt der Freigabeschritt einen
fehlenden Bericht. Es prüft vorab `GET /login` des Ziels: Antwortet es nicht mit 200, bricht es mit einer deutschen Meldung ab.
**Warum nur passiv.** Das Skript nutzt ausschließlich die klassische Spinne, die Links folgt. Den AJAX-Spider gibt es nicht
im Aufruf, weil er Formulare der Seite ausfüllen und absenden würde, und für Formulare schaltet der Haken
`.gitea/scripts/zap-hooks.py` die Verarbeitung und das Absenden der Spinne ausdrücklich ab. Aktive Regeln laufen nicht. Der
Beweis, dass dabei kein POST entsteht, wurde vor dem ersten Lauf gegen einen lokalen Testserver mit Anmeldeformular geführt
(0 POST bei allen Anfragen). Hinweis: ZAP 2.17 ignoriert bei diesem Aufruf die Option `-z`; deshalb läuft die Einstellung
über den Haken.
**Anmeldedatei für den Ausnahmefall.** Der Zugangsschutz (Basic Auth) vor alpha bleibt bestehen. Fragt alpha den Entwicklungsrechner
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
nicht weiter. Der Ordner `security-reports/` ist von Git ausgeschlossen.
## Konventionen und Fallstricke
**NestJS-Routenreihenfolge:** NestJS matcht Routen in Deklarationsreihenfolge. Eine statische Route