From d3e75c36a143424bbca4fbc5125739900123ad1a Mon Sep 17 00:00:00 2001 From: Bernd Steckmeister Date: Sat, 4 Jul 2026 19:21:19 +0200 Subject: [PATCH] =?UTF-8?q?security:=20server.py=20Restbefund=20aus=20Revi?= =?UTF-8?q?ew=20(t)=20=E2=80=93=20registration-status=20antwortet=20generi?= =?UTF-8?q?sch=20statt=20str(e)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- PROGRESS.md | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++ ROADMAP.md | 4 ++++ 2 files changed, 60 insertions(+) diff --git a/PROGRESS.md b/PROGRESS.md index 1bbcc6b..c547188 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -13,6 +13,50 @@ Schritt (und beim Abbruch mitten im Schritt den Zwischenstand). Format: --- +## 2026-07-04 – Fable-5-Review (t): (s)-Fixes geprüft – korrekt, 1 kleiner Restbefund gefunden und gefixt + +**Erledigt:** Review-Pass über die jüngste erledigte Arbeit – die zwei +(s)-Restbefund-Fixes (Commit 13b333c) kritisch gegengelesen und als Punkt (t) +im Fable-5-Review-Abschnitt abgehakt. Der (s)-Diff selbst ist korrekt (gegen +Backup `server.py.bak-20260704-review-s` verifiziert: ban/unban-Body-Lesen +sitzt vollständig VOR dem Lock inkl. Validierung, die generischen 500er auf +beiden öffentlichen POST-Routen stimmen; Dienst lief mit dem aktuellen Code, +kein unprotokollierter Rest im CHANGES-Hook-Log). Beim Ganzdatei-Gegenlesen +EIN Restbefund derselben Familie wie (s)-Befund 2: + +1. **`GET /api/registration-status` leakte Exception-Texte:** Die Route ist + öffentlich erreichbar (in `do_GET` gibt es kein Heimnetz-Gate) und + antwortete bei Fehlern mit `str(e)` – ein Lesefehler an `conduit.toml` + hätte den internen Dateipfad an Unauthentifizierte verraten. (s) hatte nur + die zwei öffentlichen POST-Routen gefixt und die öffentliche GET-Route + übersehen. Fix: gleiches Muster – generische 500-Antwort („Interner + Fehler"), Detail per stderr ins Journal. + +**Verifiziert (headless, nach Dienst-Neustart per kill/`Restart=always`):** +`py_compile` sauber, Diff gegen Backup minimal wie geplant +(`server.py.bak-20260704-review-t`). 8 Routen-Checks wie in (s) alle +unverändert (stats 200, registration-status 200, ban ohne Nutzer 400, +8-KB-Body 413, livekit-token ungültig 401, Diagnose falscher Token 403, +gespoofter Cf-Header 403, unbekannte Route 404). **500-Beweis (neu):** +`conduit.toml` für ~1 s per `chmod 000` unlesbar gemacht → +`{"error": "Interner Fehler"}` nach außen, `PermissionError` im Journal +(vorher wäre `[Errno 13] … '/home/steggi/matrix/conduit.toml'` – also der +Pfad – nach draußen gegangen); Rechte sofort wiederhergestellt (664), Route +danach wieder 200. Test-Deny-Zeile aus `security_alerts.log` 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:** Bei einem Info-Leak-Fix nicht nur die Methode fixen, in +der der Befund auftauchte: (s) hatte `do_POST` gefixt, aber `do_GET` derselben +Datei hat auch öffentliche Routen mit demselben `str(e)`-Muster. Lehre: Nach +einem Musterfund (`str(e)` an Unauthentifizierte) einmal `grep str(e)` über +die GANZE Datei und jede Fundstelle als „öffentlich oder LAN-only?" +einordnen, statt nur die Nachbarroute zu fixen. + +--- + ## 2026-07-04 – Fable-5-Review (s): (r)-Fixes geprüft – korrekt, 2 kleinere Restbefunde gefunden und gefixt **Erledigt:** Review-Pass über die jüngste erledigte Arbeit – die drei @@ -877,6 +921,18 @@ schließt den Review ab. verifiziert: 8 Routen-Checks unverändert, Lock-Beweis (hängender ban-Body, paralleler registration-status-GET in 15 ms), 500-Beweis (ungültiges JSON → generisch, Detail im Journal). Details im PROGRESS-Eintrag „(s)" oben. +- [x] **(t) (s)-Fixes (13b333c) geprüft – korrekt, 1 kleiner Restbefund gefixt + (2026-07-04).** (s)-Diff gegen Backup verifiziert (ban/unban-Body vor dem + Lock inkl. Validierung, generische 500er auf den öffentlichen POST-Routen – + alles wie protokolliert), Dienst lief mit aktuellem Code, kein + unprotokollierter Rest im CHANGES-Hook-Log. Befund beim + Ganzdatei-Gegenlesen: `GET /api/registration-status` (öffentlich, `do_GET` + hat kein Gate) antwortete bei Fehlern noch mit `str(e)` – hätte z. B. den + `conduit.toml`-Pfad geleakt; (s) hatte nur die POST-Routen gefixt. Fix: + generisches `{"error": "Interner Fehler"}`, Detail ins Journal. Headless + verifiziert: 8 Routen-Checks unverändert, 500-Beweis per kurzzeitigem + `chmod 000` auf `conduit.toml` (generisch nach außen, `PermissionError` im + Journal, danach wieder 200). Details im PROGRESS-Eintrag „(t)" oben. **Fazit:** Die Sonnet-5-Arbeit war handwerklich sauber; die zwei echten Lücken (verlorene Kommentare, fehlender Soft-Logout-Guard) hatte die abgebrochene diff --git a/ROADMAP.md b/ROADMAP.md index 27748c4..b79ccbb 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -87,6 +87,10 @@ Punkte abhaken (`[x]`), wenn erledigt UND in `PROGRESS.md` protokolliert. ADMIN_LOCK gelesen (hängender Body-Read konnte den Lock 30 s festhalten), und die öffentlichen Routen antworten bei internen Fehlern generisch statt mit Exception-Text (Info-Leak); Details ins Journal. Headless verifiziert. + Zusatz (Fable-5-Review (t), 2026-07-04): auch der öffentliche GET-Leser + `registration-status` antwortet bei internen Fehlern jetzt generisch + statt mit `str(e)` (hätte den `conduit.toml`-Pfad geleakt); headless + verifiziert inkl. 500-Beweis. - [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