Files
nexarch/mail/docs/QA-04-PRUEFPROTOKOLL.md
T
sysops 0505351e8f feat(mail): QA-04 Sicherheits-/Berechtigungsprüfung — fehlenden SMTP-Idle-Timeout gefunden und behoben
Gezielter Testangriff auf den SMTP-Pfad deckte einen realen
Härtungsfehler auf: ING-07 (Idle-Timeout via protoguard) wurde
versehentlich nur in mail/internal/imap und mail/internal/pop3
verdrahtet, SMTP bekam nie einen Timeout. Eine Gegenstelle, die eine
Kommandozeile ohne abschließendes CRLF öffnet und nie beendet, konnte
die Session unbegrenzt blockieren — real reproduziert und danach
behoben.

session.go/server.go (smtp): guard *protoguard.Guard neu, Timeout wird
in readLine() selbst gesetzt (ein Ort für Haupt-Serve-Schleife,
handleData, drainUntilDot). Neuer Konstruktor
NewServerWithMaxMessageBytesTLSLoggerRateLimitAndGuardConfig für
abweichende Timeout-Werte. Bestehende Konstruktoren bekommen automatisch
protoguard.DefaultConfig() (5 Minuten) statt wie zuvor gar keinen
Timeout — reine Härtung, keine Verhaltensänderung für funktionierende
Clients, QA-07-Lasttest bleibt unverändert grün.

Neue Tests: qa04_security_test.go (Header-Injection-Angriffe auf
Envelope-Adressen, Ressourcenerschöpfung durch nie abgeschlossene Zeile
— deckte den Fehler auf und bestätigt die Korrektur).
mailboxconfig/tenant_scoping_test.go: Stichprobe eines dritten
Speicherpfads (verschlüsselte IMAP-Zugangsdaten) — Zugriff mit echter,
bekannter fremder ID wird über alle vier Operationen zuverlässig
abgelehnt.

Rate-Limiting-Teil von Akzeptanzkriterium 3 real bestätigt (ING-09,
erneut mitgeprüft). API-Token-Teil bleibt offen: das Mail-Board besitzt
keine eigene Token-Authentifizierung, bewusst an Core-Board IAM
delegiert (QA-04s eigene Ausgangslage) — im Prüfprotokoll dokumentiert.

go build/go vet/golangci-lint clean, gesamtes Mail-Modul
regressionsfrei getestet.
2026-09-01 14:24:56 +02:00

135 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# QA-04 — Sicherheits- & Berechtigungsprüfung: Prüfprotokoll
Datum: 2026-09-01
Host: 192.168.1.131 (Build/Test/Lint), rsync + ssh
Geprüfte Pakete: `mail/internal/smtp`, `mail/internal/mailer`, `mail/internal/storage`, `mail/internal/folderstate`, `mail/internal/mailboxconfig`, `mail/internal/ratelimit`
## Umsetzung — echter Sicherheitsbefund und Korrektur
Der gezielte Testangriff auf den SMTP-Pfad (Pflichtprüfung 1) deckte
einen REALEN Härtungsfehler auf, der VOR dieser Kachel unbemerkt
geblieben war: ING-07 (Idle-Timeout-Schutz) hatte `protoguard` nur in
`mail/internal/imap` und `mail/internal/pop3` verdrahtet — `mail/
internal/smtp` bekam versehentlich NIE einen Idle-Timeout. Eine
Gegenstelle, die eine Kommandozeile ohne abschließendes CRLF öffnet und
nie beendet, konnte die Session unbegrenzt blockieren (bestätigt durch
`TestQA04_OversizedLineWithoutCRLFDoesNotHangOrCrash`, VOR der
Korrektur real reproduziert: Server antwortete nach 8s Wartezeit weder
mit Fehler noch Verbindungsende).
**Korrektur** (`session.go`/`server.go`, `mail/internal/smtp`): `guard
*protoguard.Guard` als neues Feld, Idle-Timeout wird jetzt in
`readLine()` selbst gesetzt — EIN Ort für alle Aufrufer (Haupt-Serve-
Schleife, `handleData`, `drainUntilDot`), damit auch das Lesen des
DATA-Bodys geschützt ist. Neuer Konstruktor
`NewServerWithMaxMessageBytesTLSLoggerRateLimitAndGuardConfig` für
abweichende Timeout-Werte (Tests). Bestehende Konstruktoren bekommen
automatisch `protoguard.DefaultConfig()` (5 Minuten) statt wie zuvor
gar keinen Timeout — reine Härtung, keine Verhaltensänderung für
funktionierende Clients.
## Pflichtprüfung 1: Gezielter Testangriff auf Header-Injection schlägt fehl
`TestQA04_HeaderInjectionViaEnvelopeAddressRejected`
(`smtp/qa04_security_test.go`): NUL-Byte und Steuerzeichen in
RCPT TO/MAIL FROM werden mit `553`/`501` zurückgewiesen, Session bleibt
danach funktionsfähig, keine Nachricht erreicht den Sink. Ergänzt um
`TestQA04_OversizedLineWithoutCRLFDoesNotHangOrCrash` (Ressourcen-
erschöpfungsangriff, siehe Abschnitt "Umsetzung" — deckte den realen
Härtungsfehler auf und bestätigt nach der Korrektur zuverlässige
Reaktion binnen des konfigurierten Timeouts). Bereits bestehende,
unverändert gültige Nachweise aus ING-03/ING-06 werden mitgezählt:
CRLF-Injection in Betreff/Anzeigename (`mailer.TestHeaderWriter_
RejectsControlCharsAndCRLFInSubjectAndDisplayName`), Dot-Stuffing
korrekt gegen DATA-Command-Smuggling (`smtp.TestData_
MessageSizeCheckedBeforeAcceptance` u. a.), TLS-Downgrade-Angriffe
(`smtp.TestServer_RejectsLegacyTLSVersionAndWeakCiphers`, ING-06).
Ergebnis: **BESTANDEN** — inklusive eines real gefundenen und
behobenen Härtungsfehlers.
## Pflichtprüfung 2: Stichprobenprüfung mehrerer Speicherpfade auf Mandantentrennung
Drei unabhängige Speicherpfade stichprobenartig geprüft:
1. **Objekt-Storage** (`mail/internal/storage`, ARC-06): physische
Bucket-Trennung, bereits real gegen MinIO nachgewiesen
(`TestProvisionTenant_CreatesPhysicallySeparateBuckets`,
`TestAccessWithoutTenantContext_FailsBecauseNoBucketReferenceable`
— siehe `ARC-06-PRUEFPROTOKOLL.md`).
2. **Folder-State** (`mail/internal/folderstate`, ING-10):
`NextUID`/`Rebuild` für Mandant A verändern Mandant Bs Zustand
nachweislich nicht (`TestTenantScoping_
NeverReturnsOrMutatesOtherTenantsFolderState`).
3. **Postfachkonfiguration** (`mail/internal/mailboxconfig`) — NEU für
diese Kachel, bislang nicht auditiert, besonders sensibel
(verschlüsselte IMAP-Zugangsdaten): `TestTenantScoping_
ForeignKnownIDNeverAccessible` — Mandant B versucht mit einer ECHTEN,
bekannten ID aus Mandant As Zeile (realistischster Angriffsfall bei
fortlaufenden IDs in einer gemeinsamen Tabelle) auf
`List`/`GetDecryptedPassword`/`Update`/`Delete` zuzugreifen — jeder
Versuch liefert `ErrNotFound`, Mandant As Daten bleiben unverändert.
Ergebnis: **BESTANDEN** in allen drei gezogenen Stichproben.
## Pflichtprüfung 3: Test: API-Zugriff mit widerrufenem/fremdem Token wird verweigert
**Teilweise nicht durchführbar, dokumentiert:** Das Mail-Modul besitzt
aktuell KEINE eigene HTTP-API mit Token-/Session-Authentifizierung —
jede vorhandene Schnittstelle (`web/mail-search`, SRC-04) verweist
explizit auf eine noch ausstehende "zentrale Session-/IAM-Anbindung
(Core-Board-Scope, nicht Bestandteil dieser Kachel)", konsistent mit
QA-04s eigener Ausgangslage: "Berührt Login-Tenant-Filter und
Privilege-Escalation dafür ist bereits Core-Board IAM zuständig, hier
nur Mail-spezifische Aspekte prüfen." Es gibt daher keinen Prüfgegenstand
für "widerrufenes/fremdes API-Token" innerhalb des Mail-Boards — dieser
Teil bleibt **offen**, bis Core-Board IAM eine Token-Schnittstelle
liefert, gegen die geprüft werden kann.
Der **Rate-Limiting-Teil** von Akzeptanzkriterium 3 ist dagegen real
vorhanden und geprüft (ING-09): `TestRateLimit_
LoadExceedingLimitGetsRejectedWithRetryHint`,
`TestRateLimit_LegitUsageBelowThresholdUnaffected`,
`TestRateLimit_PerTenantIndependentAndEffective` — je einmal in IMAP,
POP3, SMTP, alle mit echten Nachweisen bestanden (siehe
`ING-09-PRUEFPROTOKOLL.md`), hier erneut mitgeprüft und bestätigt grün.
Ergebnis: **Rate-Limiting-Teil BESTANDEN, API-Token-Teil OFFEN**
(kein Prüfgegenstand im Mail-Board vorhanden).
## Akzeptanzkriterien
1. **Prüfung bestätigt wirksame Härtung des SMTP-Pfads gegen bekannte
Angriffsmuster**: durch Pflichtprüfung 1 belegt — inklusive eines
real gefundenen und in dieser Kachel behobenen Härtungsfehlers
(fehlender Idle-Timeout).
2. **Prüfung bestätigt lückenlose Mandantentrennung im Speicherpfad**:
durch Pflichtprüfung 2 belegt (drei Speicherpfade, keine Lücke
gefunden).
3. **Prüfung bestätigt korrekt greifendes API-Token-/Rate-Limiting**:
Rate-Limiting-Teil durch Pflichtprüfung 3 belegt; API-Token-Teil
bleibt offen (kein Prüfgegenstand, siehe oben).
## Build/Vet/Lint/Test — Gesamtmodul
```
go build ./... → OK
go vet ./... → OK
golangci-lint run ./... → 0 issues
go test ./... -p 1 (TEST_TENANT_DSN, TEST_MANTICORE_URL, TEST_S3_ENDPOINT/TEST_S3_ACCESS_KEY/TEST_S3_SECRET_KEY gesetzt) → alle Pakete ok
```
Keine Regression — insbesondere QA-07-Lasttest für SMTP bleibt nach der
Idle-Timeout-Korrektur unverändert grün (6057,8 Sessions/s, p95 48,2ms).
## Ergebnis
QA-04 erfüllt Akzeptanzkriterium 1 und 2 vollständig mit echten,
ausgeführten Nachweisen — inklusive eines real gefundenen und behobenen
Sicherheitsfehlers (fehlender SMTP-Idle-Timeout). Akzeptanzkriterium 3
ist zur Hälfte (Rate-Limiting) erfüllt; die API-Token-Hälfte bleibt
offen, da im Mail-Board kein Prüfgegenstand existiert (bewusst an
Core-Board IAM delegiert, siehe QA-04s eigene Ausgangslage). Board wird
auf Basis der erfüllbaren Teile fortgeführt, das offene Element ist
hier und im Entscheidungsverlauf vermerkt. Freigeschaltet: QA-09.