docs(quick-261009-p0m): Sicherheitsprotokoll mit Bestandsaufnahme und erster Vollpruefung

- docs/sicherheitsprotokoll.md: alle bisherigen Pruefungen (acht Code-Pruefungen,
  Bedrohungsbetrachtungen, Datentrennung, Fehlerregister), erste vollstaendige
  Pruefung vom 9.10.2026 mit Zahlen und Einordnung jedes Befunds
- Links aus docs/README.md, Betriebs- und Entwicklungsanleitung; Entwicklungsanleitung
  mit Abschnitt Sicherheitspruefungen und Pflegeregel
- CHANGELOG: Sicherheits-Eintrag unter Neu

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-10-09 19:33:44 +02:00
parent 3d00be8292
commit 5b36b9a564
5 changed files with 322 additions and 1 deletions
+74 -1
View File
@@ -16,7 +16,8 @@ Code geprüft, nicht aus einer geplanten Architektur abgeleitet.
6. [Berechtigungen](#berechtigungen)
7. [Datenbank und Migrationen](#datenbank-und-migrationen)
8. [Tests](#tests)
9. [Konventionen und Fallstricke](#konventionen-und-fallstricke)
9. [Sicherheitsprüfungen](#sicherheitsprüfungen)
10. [Konventionen und Fallstricke](#konventionen-und-fallstricke)
---
@@ -834,6 +835,78 @@ cargo clippy
Beide laufen auch im CI-Job `desktop` (D-16); ein grüner `cargo clippy` ohne
Warnungen ist Voraussetzung für den Bauschritt.
## Sicherheitsprüfungen
Tessera führt ein eigenes [Sicherheitsprotokoll](sicherheitsprotokoll.md). Es hält für die Inhaberin oder den Inhaber und
für Kunden fest, was geprüft wurde, was dabei herauskam und was daraus geworden ist. Dieser Abschnitt sagt, wie Sie es
aktuell halten, was die Pipeline automatisch prüft und wie Sie die Prüfung selbst wiederholen.
### So pflegen Sie dieses Protokoll
Jede der folgenden Gelegenheiten bekommt im selben Auftrag einen Eintrag unter „Verlauf“ in
`docs/sicherheitsprotokoll.md` (neuester Eintrag oben):
- jede **Sicherheitsprüfung** (Code-Prüfung nach einer größeren Änderung, Bedrohungsbetrachtung, neue Prüf-Tests mit
Sicherheitsbezug),
- jede **festgehaltene Messung** der automatischen Prüfung: die erste, jede nach dem Beheben von Befunden und jede, bei der
sich die Zahlen der Pipeline auffällig ändern (zum Beispiel ein neuer kritischer Fund),
- jeder **Lauf der Außenprüfung** vor einer Freigabe.
Der Eintrag nennt das Datum, was geprüft wurde, die Zahlen und was behoben oder bewusst hingenommen wurde. Im selben
Auftrag werden „Auf einen Blick“ und die Tabelle „Einordnung der Befunde“ auf den neuen Stand gebracht. Jeder Befund trägt
einen der drei Stände „behoben“, „bewusst akzeptiert“ oder „offen“, und bei „offen“ und „bewusst akzeptiert“ steht immer
ein Grund. Das Protokoll enthält nie Geheimnisse (Passwörter, Schlüssel, Zugangscodes) und nie Einzelheiten, mit denen
sich ein Fehler ausnutzen ließe; Bausteine und Schweregrade werden in Alltagssprache genannt. Schreibweise wie in allen
Anleitungen: Sie-Form, echte Umlaute, Fachbegriffe beim ersten Auftreten erklärt.
### Die Prüfung in der Pipeline
Nach dem Bau der Abbilder läuft in `.gitea/workflows/ci.yml` der Job `security` („Sicherheitsprüfung (nur Bericht)“). Er
läuft nur bei Pushes auf `main` und bei Marken `v*`, bekommt kein Secret, ist als `continue-on-error` markiert und wird von
keinem anderen Job abgewartet: Er kann weder Bau noch Tests noch die Veröffentlichung aufhalten. Alles Eigentliche steckt in
`.gitea/scripts/security-scan.sh`:
- 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
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 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).
### Prüfungen von Hand wiederholen
Vom Hauptordner des Repositorys aus:
```bash
sh .gitea/scripts/security-scan.sh --print-plan # zeigt Werkzeuge und Abbilder, ohne Netz
sh .gitea/scripts/security-scan.sh all # installiert fehlende Werkzeuge und prüft alles
SCAN_IMAGES="tessera-ctl-api:latest" sh .gitea/scripts/security-scan.sh run # ein lokales Abbild
```
Das Skript prüft nur den **eingecheckten** Stand; ungespeicherte Änderungen sehen die Werkzeuge nicht. Mit der Umgebungsvariable
`SCAN_IMAGES` (Abbilder durch Leerzeichen getrennt) prüfen Sie lokal gebaute Abbilder. Die Berichte liegen im Ordner
`security-reports/` (von Git und vom Docker-Build ausgeschlossen); die Zeilen `SECURITY-SUMMARY` stehen auch in
`security-reports/summary.txt`. Das Skript beendet sich immer mit Exit 0; ob ein Fund wichtig ist, entscheiden Sie anhand der
Zahlen.
### Ausnahmelisten
Zwei Dateien nehmen geprüfte Fehlalarme aus den Berichten: `.gitleaks.toml` (Zugangsdaten) und `.semgrepignore` (statische
Code-Analyse). Die Regeln:
- Aufgenommen wird nur, was von Hand als **Fehlalarm** geprüft wurde. Ein neuer Treffer wird nie vorsorglich freigegeben; ein
echtes Geheimnis wird gemeldet und gemeinsam mit der Inhaberin oder dem Inhaber behandelt, nicht eingetragen.
- Die Ausnahme ist so **eng wie möglich**: eine einzelne Datei mit verankertem Pfad und der betroffenen Regel, bei Dateien, die
keine Tests oder Notizen sind, zusätzlich die eine geprüfte Zeile. Nur der Ordner mit den Testschlüsseln des
Zertifikatsmanagers (`apps/api/src/cert-manager/__fixtures__/`) ist als ganzer Ordner freigegeben, denn er existiert, um
Testschlüssel zu enthalten.
- 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.
## Konventionen und Fallstricke
**NestJS-Routenreihenfolge:** NestJS matcht Routen in Deklarationsreihenfolge. Eine statische Route