audit:export gatete nichts - Export hing an audit:read

Bei der Gegenprobe zur neuen Rolle "Gegenbuch" gefunden: Ein Konto mit
ausschliesslich audit:read bekam auf GET /audit-logs/export eine 200. Die
Berechtigung audit:export stand im Katalog und in der Rollenverwaltung -
und wurde nirgends geprueft.

Der Unterschied ist nicht kosmetisch. Blaettern zeigt 50 Zeilen; der
Export liefert in einem Zug das gesamte Protokoll inklusive changesBefore
und changesAfter, also der vollstaendigen Vorher/Nachher-Datensaetze,
dazu resourceLabel mit Klartextnamen, IP-Adressen und User-Agents. Live
nachgewiesen auf Staging: 43 Eintraege mit gefuellter resourceLabel
allein fuer resourceType=Customer.

Damit konnte ausgerechnet das Dienstkonto des Gegenbuchs Personendaten
exportieren - das Konto, dessen Passwort im Klartext in der .env auf der
Notar-Maschine liegt, und dem README und Rollenname "nur Pruefwerte
lesen" zusichern.

/audit-logs/export verlangt jetzt audit:export. Betroffen ist genau eine
Rolle: Gegenbuch, und zwar gewollt. Die DSGVO-Rolle traegt audit:*
vollstaendig und behaelt den Export.

In der Oberflaeche erscheinen JSON- und CSV-Knopf nur noch mit
audit:export - sonst stuenden dort Knoepfe, die zuverlaessig 403 liefern.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-26 12:56:53 +02:00
co-authored by Claude Opus 5
parent d2460fa7c0
commit 23505afc05
4 changed files with 63 additions and 14 deletions
+11 -1
View File
@@ -16,7 +16,17 @@ router.use(authenticate);
router.get('/', requirePermission('audit:read'), auditLogController.getAuditLogs);
// Audit-Logs exportieren
router.get('/export', requirePermission('audit:read'), auditLogController.exportAuditLogs);
//
// Verlangt `audit:export`, nicht `audit:read`. Die Berechtigung stand im
// Katalog und in der Rollenverwaltung, gatete aber NICHTS - jeder Leser
// konnte das vollstaendige Protokoll in einem Zug herausziehen.
//
// Das ist etwas anderes als Blaettern: Der Export liefert `changesBefore` und
// `changesAfter`, also die vollstaendigen Vorher/Nachher-Datensaetze, dazu
// `resourceLabel` mit Klartextnamen, IP-Adressen und User-Agents. Aufgefallen
// am Dienstkonto des Gegenbuchs: Es soll ausschliesslich Pruefwerte lesen -
// und konnte Personendaten exportieren.
router.get('/export', requirePermission('audit:export'), auditLogController.exportAuditLogs);
// Retention-Policies
router.get('/retention-policies', requirePermission('audit:admin'), auditLogController.getRetentionPolicies);