Security-Hardening Runde 3: JWT, trust-proxy, weitere IDORs, Attachment-Härtung

- JWT-Algorithmus fest auf HS256 (Defense-in-Depth gegen alg-confusion)
- app.set('trust proxy', 1) – Rate-Limiter wirkt jetzt auch hinter Reverse-Proxy
- IDOR-Fix: Invoice-ECD-Endpoints + PDF-Template-Generierung (canAccessContract/ECD)
- Email-Anhang-Download: Content-Type-Safelist, SVG nie inline, nosniff, Filename-CRLF-Sanitize
- Provider/Tariff-GET-Routen: requirePermission('providers:read') (Portal-Kunden raus)
- SMTP-Header-Injection zentral in sendEmail blockiert (schützt alle Caller)
- bcrypt-Cost 10 → 12 (OWASP 2026)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-24 09:38:25 +02:00
parent 301aafffd1
commit 8aead8c2f6
11 changed files with 131 additions and 21 deletions
+21
View File
@@ -224,3 +224,24 @@ export async function canAccessCachedEmail(
'E-Mail',
);
}
/**
* Zugriff auf ein EnergyContractDetails prüfen (ECD → Contract → customerId).
*/
export async function canAccessEnergyContractDetails(
req: AuthRequest,
res: Response,
ecdId: number,
): Promise<boolean> {
if (!req.user?.isCustomerPortal) return true;
const ecd = await prisma.energyContractDetails.findUnique({
where: { id: ecdId },
select: { contract: { select: { customerId: true } } },
});
return canAccessResourceByCustomerId(
req,
res,
ecd?.contract?.customerId,
'Energievertrag',
);
}