Feature-Spec, INDEX.md und features.ts für PROJ-72 (Superadmin-Peer-Patch-Fix) ergänzt inkl. QA-Ergebnisse. Zusätzlich: abgelehnte Privilege-Escalation-/ Tenant-Isolation-Versuche (403) werden jetzt als Success:false im Audit-Log protokolliert (vorher nur erfolgreiche Updates) - Härtungspunkt aus QA-Runde.
2.9 KiB
id, title, status, created
| id | title | status | created |
|---|---|---|---|
| PROJ-72 | Fix Superadmin kann Passwort/Rolle von Superadmin-Peers nicht ändern (Sicherheitsbug) | Deployed | 2026-07-26 |
Problem
handleUpdateUser (internal/api/admin_users_handlers.go) blockierte per
SEC-01-Privilegien-Check (roleLevel(target.Role) >= roleLevel(sess.Role))
jede Modifikation an Ziel-Usern mit gleichem oder höherem Rollen-Level wie der
Aufrufer. Da Superadmin das höchste Level ist (roleLevel = 5), traf dieser
Vergleich auch Superadmin-vs-Superadmin zu: ein Superadmin konnte weder sich
selbst noch andere Superadmins bearbeiten — u.a. kein Passwort-Reset für
andere Superadmins möglich.
Lösung
Peer-Level-Check (>=-Vergleich für Ziel-Rolle und Rollen-Zuweisung) gilt nur
noch für sess.Role != userstore.RoleSuperAdmin. Superadmin ist die höchste
Stufe — es gibt keine höhere Rolle, vor der geschützt werden müsste, daher ist
Superadmin von diesem Peer-Check ausgenommen.
Zusätzlich: abgelehnte Privilege-Escalation-/Tenant-Isolation-Versuche (403)
werden jetzt im Audit-Log als Success: false protokolliert (vorher nur
erfolgreiche Updates geloggt) — Härtung, während QA-Verifikation entdeckt.
Implementation Notes
internal/api/admin_users_handlers.gohandleUpdateUser:- Peer-Level-Check (Ziel-Rolle + Rollen-Zuweisung) in
if sess.Role != userstore.RoleSuperAdmin { ... }gekapselt. - Audit-Log-Eintrag (
Success: false) bei: Cross-Tenant-Zugriff verweigert, Privilegien für Ziel-User-Modifikation fehlen, Privilegien für Rollen-Zuweisung fehlen. handleCreateUser: Audit-Log-Eintrag (Success: false) bei verweigerter Rollen-Zuweisung beim Anlegen.
- Peer-Level-Check (Ziel-Rolle + Rollen-Zuweisung) in
- Tenant-Isolation-Check (SEC-02) unverändert — Superadmin hat
TenantID == nil, überspringt diesen Block ohnehin.
Acceptance Criteria
- Superadmin kann eigenes Passwort/Rolle/aktiv-Status ändern (Self-Patch).
- Superadmin kann Passwort/Rolle/aktiv-Status eines anderen Superadmins ändern (Peer-Patch).
- domain_admin kann weiterhin KEINE Peer- oder höherrangigen User (inkl. Superadmin) patchen (403).
- Cross-Tenant-Zugriff (IDOR) weiterhin blockiert (403).
- Kein Auth-Bypass (401 ohne gültigen Token).
- Abgelehnte Privilege-Escalation-Versuche erscheinen im Audit-Log
(
Success: false).
QA Test Results (2026-07-27, gegen 192.168.1.132)
| TC | Erwartung | Ergebnis |
|---|---|---|
| Superadmin patcht Peer-Superadmin (Rolle+Passwort+aktiv) | 200 | PASS |
| Superadmin Self-Patch | 200 | PASS |
| domain_admin patcht Superadmin (global) | 403 | PASS |
| domain_admin patcht Peer-domain_admin (gleicher Tenant) | 403 | PASS |
| domain_admin patcht User aus fremdem Tenant (IDOR) | 403 | PASS |
| PATCH ohne JWT | 401 | PASS |
| domain_admin weist eigenem Tenant-User Rolle "admin" zu | 403 | PASS |
| domain_admin patcht regulären User im eigenen Tenant (Positivkontrolle) | 200 | PASS |
Deployed auf 131 (Produktiv) und 132 (teilproduktiv) am 2026-07-26/27.