Pentest R93: Leerer String != fehlender Query-Param

R93.1 INFO: ?accountId= (explizit-leer) wurde wie ?accountId
weggelassen behandelt → 200 statt 400 auf optionalen Endpunkten.
Pentester-Spec: leerer String ist keine gültige Zahl.

Fix in parsePositiveIntQuery: nur `v === undefined` ist absent;
'', '  ', alles andere muss parsen. Required + optional Modes
unverändert. Sanity-Test: alle 11 Cases grün.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-21 14:54:15 +02:00
parent caa283e66f
commit c013e1e747
2 changed files with 26 additions and 3 deletions
@@ -64,8 +64,13 @@ function parsePositiveIntQuery(
res: Response,
options?: { required?: boolean },
): number | undefined | null {
const absent = v === undefined || v === '' || (typeof v === 'string' && v.trim() === '');
if (absent) {
// Pentest 93.1 (INFO, 2026-06-21): `?accountId=` (explizit-leer) wurde
// wie `?accountId` weggelassen behandelt → 200 statt 400 auf optionalen
// Endpunkten. Spec sagt aber: leerer String ist KEINE gültige Zahl.
// Trennung jetzt strikt:
// - Param fehlt komplett (`undefined`) → "absent"
// - Param da, aber Wert leer/Whitespace/keine Zahl → invalid → 400
if (v === undefined) {
if (options?.required) {
res.status(400).json({
success: false,
@@ -82,7 +87,15 @@ function parsePositiveIntQuery(
} as ApiResponse);
return null;
}
const n = parseInt(v, 10);
const trimmed = v.trim();
if (trimmed === '') {
res.status(400).json({
success: false,
error: `${fieldLabel} darf nicht leer sein bitte weglassen oder positive Ganzzahl angeben.`,
} as ApiResponse);
return null;
}
const n = parseInt(trimmed, 10);
if (!Number.isFinite(n) || n < 1 || !Number.isInteger(n)) {
res.status(400).json({
success: false,
+10
View File
@@ -97,6 +97,16 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung
## ✅ Erledigt
- [x] **🔒 Pentest R93 Leerer String != fehlender Param**
- R93.1 (INFO): `?accountId=` (explizit-leer) wurde wie `?accountId`
weggelassen behandelt → 200 statt 400 auf optionalen Endpunkten.
Pentester-Spec: leerer String ist KEINE gültige Zahl.
- Fix im `parsePositiveIntQuery()`-Helper: striktere Absent-Logik
(`v === undefined` ist absent; `''`, `' '`, alles andere muss
parsen). Required + optional Modes unverändert.
- Float-Grenzfall (`accountId=5.5` → 5 via `parseInt`) bleibt als
by-design akzeptiert (Pentester-Bestätigung, kein Security-Impact).
- [x] **🔒 Pentest R92 Strict-400 für accountId auf Vertrags-Endpunkten**
- R91-Fix war silent-undefined bei invaliden Werten: `accountId=abc`
auf `GET /contracts/:id/emails` ergab "kein Filter" → Mailbox-