getCockpit fail-closed (R146) - konsistent zu listAll/getContracts
Pentester R146 (Konsistenz + Defense-in-Depth): getCockpit war der
einzige der drei Geschwister-Endpunkte noch auf dem alten Fail-open-
Muster. Der Cockpit-SERVICE ist bereits fail-closed (customerIds:[] ->
IN () -> 0), aber der CONTROLLER uebergab bei falsy customerId
undefined statt [] -> {} -> alle Kunden. Genau die R4-HIGH-Stelle
'Cockpit leakt alle Vertraege'.
Jetzt: Portal-Token wird IMMER gescoped (ohne customerId -> []),
identischer Einzeiler wie listAll/getContracts. Nicht erreichbar (Token
traegt immer customerId), aber der urspruengliche HIGH-Endpunkt soll
nicht das letzte Fail-open-Muster bleiben.
Verifiziert: Cockpit Staff -> 17 Vertraege; Portal []->0 (contracts +
cancellationConfirmations).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -633,14 +633,19 @@ export async function getCockpit(req: AuthRequest, res: Response): Promise<void>
|
|||||||
// Portal-User dürfen nur ihre eigenen + vertretene Kunden (mit Vollmacht) sehen.
|
// Portal-User dürfen nur ihre eigenen + vertretene Kunden (mit Vollmacht) sehen.
|
||||||
// Analog zu getContracts. Sonst leakt das Cockpit ALLE Verträge ALLER Kunden
|
// Analog zu getContracts. Sonst leakt das Cockpit ALLE Verträge ALLER Kunden
|
||||||
// (Pentest Runde 4, 2026-05-16: HOCH).
|
// (Pentest Runde 4, 2026-05-16: HOCH).
|
||||||
|
// Fail-closed (Pentest R146): Portal-Token wird IMMER gescoped; fehlt wider
|
||||||
|
// Erwarten die customerId, ergibt das eine leere Menge (nicht alle) – der
|
||||||
|
// Cockpit-Service filtert `customerIds: []` bereits als „keine Treffer".
|
||||||
let customerIds: number[] | undefined;
|
let customerIds: number[] | undefined;
|
||||||
if (req.user?.isCustomerPortal && req.user.customerId) {
|
if (req.user?.isCustomerPortal) {
|
||||||
customerIds = [req.user.customerId];
|
customerIds = req.user.customerId ? [req.user.customerId] : [];
|
||||||
const representedIds: number[] = req.user.representedCustomerIds || [];
|
if (req.user.customerId) {
|
||||||
for (const repCustId of representedIds) {
|
const representedIds: number[] = req.user.representedCustomerIds || [];
|
||||||
const hasAuth = await authorizationService.hasAuthorization(repCustId, req.user.customerId);
|
for (const repCustId of representedIds) {
|
||||||
if (hasAuth) {
|
const hasAuth = await authorizationService.hasAuthorization(repCustId, req.user.customerId);
|
||||||
customerIds.push(repCustId);
|
if (hasAuth) {
|
||||||
|
customerIds.push(repCustId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user