security: server.py multithreaded + Diag-Log-Lock (Review-Befund p, Threading-Haertung vollendet)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Bernd Steckmeister
2026-07-04 13:51:32 +02:00
parent 455742d1bf
commit 343545b59e
3 changed files with 64 additions and 0 deletions
+9
View File
@@ -1251,3 +1251,12 @@
2026-07-04 09:16 [Edit] /home/steggi/pyramid/ROADMAP.md
2026-07-04 09:17 [Edit] /home/steggi/pyramid/PROGRESS.md
2026-07-04 09:17 [Edit] /home/steggi/pyramid/PROGRESS.md
2026-07-04 09:18 [Edit] /home/steggi/.claude-pyramid/projects/-home-steggi-pyramid/memory/pyramid-arbeitsstand.md
2026-07-04 09:43 [Edit] /home/steggi/matrix/server.py
2026-07-04 09:43 [Edit] /home/steggi/matrix/server.py
2026-07-04 09:43 [Edit] /home/steggi/matrix/server.py
2026-07-04 13:46 [Edit] /home/steggi/matrix/server.py
2026-07-04 13:46 [Edit] /home/steggi/matrix/server.py
2026-07-04 13:50 [Edit] /home/steggi/pyramid/PROGRESS.md
2026-07-04 13:51 [Edit] /home/steggi/pyramid/PROGRESS.md
2026-07-04 13:51 [Edit] /home/steggi/pyramid/ROADMAP.md
+52
View File
@@ -13,6 +13,45 @@ Schritt (und beim Abbruch mitten im Schritt den Zwischenstand). Format:
---
## 2026-07-04 Fable-5-Review (p): Interims-Gate geprüft (korrekt) + halbfertige Threading-Härtung einer abgebrochenen Session vollendet
**Erledigt:** Review-Pass über die jüngste erledigte Arbeit (Interims-Gate,
Commits e97a748/455742d) als Punkt (p) im Fable-5-Review-Abschnitt abgehakt.
Das Gate selbst ist korrekt (Socket-IP als belastbare Prüfung, Cf-Header nur
Zweitschranke, Deny-Log gedeckelt, kein Angreifer-Text im Log). Dabei über das
CHANGES.md-Hook-Log entdeckt: Eine Session hat um 09:43 (NACH dem letzten
Commit) **drei unprotokollierte server.py-Edits** gemacht und wurde mitten in
einer Threading-Härtung abgebrochen `threading`-Import + `DIAG_LOCK` waren da,
aber der Lock wurde **nirgends benutzt**, und die eigentliche Umstellung auf
`ThreadingHTTPServer` fehlte (der Kommentar behauptete sie schon). Obendrein
lief der Dienst noch mit dem Code von 09:14 nichts davon war je geladen.
Die angefangene Härtung ist fachlich richtig (der single-threaded `HTTPServer`
ließ EINEN langsamen Client den ganzen Server blockieren inkl. des öffentlich
erreichbaren `/api/livekit-token`), darum vollendet statt zurückgebaut:
`ThreadingHTTPServer` in `__main__`, Diagnose-Log-Kappen+Anhängen in den
`DIAG_LOCK` gewickelt (einziger öffentlich beschreibbarer Pfad), `timeout = 30`
der Vorsession belassen. Dienst-Neustart (kill/`Restart=always`), headless
verifiziert (11 Prüfungen): stats 200; Admin-Route localhost UND 192.168.178.71
→ 400 „Kein Nutzer angegeben"; öffentlich UND gespoofter Cf-Header → 403;
livekit-token ungültig → 401; Diagnose falscher Token 403, gültig 200 + im Log,
300 KB → 413; **Slow-Loris-Test: parallele Anfrage in 10 ms beantwortet,
während ein Client hing** (vorher unmöglich), hängender Body-Read nach exakt
~30 s serverseitig beendet, Dienst danach gesund. Test-Einträge aus beiden
Logs wieder entfernt.
**Offen/Nächster Schritt:** Unverändert alle offenen ROADMAP-Punkte brauchen
PC/Gerät (SQLCipher, LiveKit-Client-Umstellung, Härtetest) oder Bernd
(Secret-Rotation, Dashboard-Fernzugriff A/B, Call-Pilot-Go).
**Stolperfallen:** (1) Das CHANGES.md-Hook-Log ist der zuverlässigste Detektor
für unprotokollierte Arbeit abgebrochener Sessions Zeitstempel der letzten
Einträge mit dem letzten Commit vergleichen. (2) „Datei geändert" heißt NICHT
„läuft": Dienststart-Zeit (`systemctl status`) gegen Datei-mtime prüfen hier
lagen 30 Minuten Code unausgeführt auf der Platte. (3) Ein definierter, aber
nie benutzter Lock ist ein Halbfertig-Marker, kein Schutz.
---
## 2026-07-04 Dashboard-Befund (o): akutes Loch mit aussperr-sicherem Interims-Gate geschlossen
**Erledigt:** Der KRITISCHE Befund (o) (Dashboard-Admin-Endpoints ohne Auth,
@@ -632,6 +671,19 @@ schließt den Review ab.
einem aussperr-sicheren Interims-Gate geschlossen (Admin-Routen nur noch
Heimnetz/localhost, siehe PROGRESS-Eintrag „Dashboard-Befund (o)" oben)
offen bleibt nur noch die Fernzugriffs-Entscheidung A/B.
- [x] **(p) Interims-Gate (e97a748/455742d) reviewt korrekt; dabei halbfertige,
unprotokollierte Threading-Härtung einer abgebrochenen Session gefunden und
vollendet (2026-07-04).** Gate-Logik bestätigt: Socket-IP ist die belastbare
Prüfung (nicht spoofbar), Cf-Header nur Zweitschranke, Deny-Log mit 5-MB-Deckel
und ohne attacker-kontrollierten Text; Restrisiken (LAN-CSRF, offene
Nutzerlisten-Ansicht) waren bereits in `docs/DASHBOARD_AUTH_HARDENING.md`
dokumentiert kein neuer Befund am Gate. ABER: CHANGES-Hook zeigte drei
server.py-Edits um 09:43 ohne Commit/Protokoll abgebrochene Session hatte
`DIAG_LOCK` definiert, aber nie benutzt, und `ThreadingHTTPServer` im Kommentar
behauptet, aber nicht umgestellt; der Dienst lief zudem noch mit altem Code.
Vollendet (Threading + Lock-Nutzung), Dienst neu gestartet, 11 Headless-
Prüfungen grün inkl. Slow-Loris (parallele Anfrage 10 ms statt blockiert;
hängender Body-Read nach 30 s gekappt). Details im PROGRESS-Eintrag „(p)" oben.
**Fazit:** Die Sonnet-5-Arbeit war handwerklich sauber; die zwei echten Lücken
(verlorene Kommentare, fehlender Soft-Logout-Guard) hatte die abgebrochene
+3
View File
@@ -71,6 +71,9 @@ Punkte abhaken (`[x]`), wenn erledigt UND in `PROGRESS.md` protokolliert.
Admin-Buttons auch von unterwegs? Dann Weg A (Cloudflare Access, empfohlen
schließt auch die weiterhin öffentliche Nutzerlisten-Ansicht) oder Weg B
(`DASH_TOKEN`), Plan + Restrisiken in `docs/DASHBOARD_AUTH_HARDENING.md`.
Zusatz (Fable-5-Review (p), 2026-07-04): `server.py` läuft jetzt multithreaded
mit 30-s-Socket-Timeout ein einzelner langsamer Client kann den Server
(und damit `/api/livekit-token`) nicht mehr blockieren; headless verifiziert.
- [x] **LiveKit-Token-Route server-seitig gebaut + verifiziert** (Fable-5-Review (n),
PROGRESS.md 2026-07-04). `POST /api/livekit-token` läuft live in `server.py`
(whoami-Auth, stdlib-HS256-Minting aus `livekit.yaml`), headless geprüft