diff --git a/backend/src/controllers/contract.controller.ts b/backend/src/controllers/contract.controller.ts index 79787f29..13174d86 100644 --- a/backend/src/controllers/contract.controller.ts +++ b/backend/src/controllers/contract.controller.ts @@ -633,14 +633,19 @@ export async function getCockpit(req: AuthRequest, res: Response): Promise // Portal-User dürfen nur ihre eigenen + vertretene Kunden (mit Vollmacht) sehen. // Analog zu getContracts. Sonst leakt das Cockpit ALLE Verträge ALLER Kunden // (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; - if (req.user?.isCustomerPortal && req.user.customerId) { - customerIds = [req.user.customerId]; - const representedIds: number[] = req.user.representedCustomerIds || []; - for (const repCustId of representedIds) { - const hasAuth = await authorizationService.hasAuthorization(repCustId, req.user.customerId); - if (hasAuth) { - customerIds.push(repCustId); + if (req.user?.isCustomerPortal) { + customerIds = req.user.customerId ? [req.user.customerId] : []; + if (req.user.customerId) { + const representedIds: number[] = req.user.representedCustomerIds || []; + for (const repCustId of representedIds) { + const hasAuth = await authorizationService.hasAuthorization(repCustId, req.user.customerId); + if (hasAuth) { + customerIds.push(repCustId); + } } } }