Pentest R95: portalUsername (Manual-Modus) härten
R95.1 MEDIUM: foo\r\nBcc:evil@x.de → Header-Injection-Vektor R95.3 LOW: <script>...</script>@x.de → silent stripHtml-Mutation R95.4 LOW: >190 Zeichen → VARCHAR-Overflow → 500 statt 400 Fix: validatePortalUsername() in sanitize.ts mit Whitelist ^[A-Za-z0-9_\-/.@+ ]{0,100}$. Strukturell sind CRLF, Tab, alle Control-Chars, Tags und Quotes raus → R95.1+R95.3 ohne extra Check. Max 100 → ApiError(400) → R95.4. Raw-Input vor stripHtml geprüft (R87-Pattern). Eingehängt in sanitizeContractBody. R95.2 (Email-Format-Pflicht) bewusst NICHT übernommen: portalUsername ist im Manual-Modus nicht zwingend eine Email (Vodafone, 1&1, EWE und Stadtwerke nutzen Kundennummern oder Pseudonyme als Portal-Login). Doku in SECURITY-HARDENING.md § Runde 95. Frontend: maxLength={100} am Input als UX-Schicht. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,7 @@ import * as authorizationService from '../services/authorization.service.js';
|
||||
import { recordPredecessorFinalReading } from '../services/customer.service.js';
|
||||
import { ApiResponse, AuthRequest } from '../types/index.js';
|
||||
import { logChange } from '../services/audit.service.js';
|
||||
import { sanitizeContract, sanitizeContractStrict, sanitizeContracts, sanitizeContractsStrict, stripHtml, sanitizeNotes, validateContractDocumentType, validateOptionalIsoDate, isContractIdentifierField, validateContractIdentifier } from '../utils/sanitize.js';
|
||||
import { sanitizeContract, sanitizeContractStrict, sanitizeContracts, sanitizeContractsStrict, stripHtml, sanitizeNotes, validateContractDocumentType, validateOptionalIsoDate, isContractIdentifierField, validateContractIdentifier, validatePortalUsername } from '../utils/sanitize.js';
|
||||
import { ApiError } from '../utils/apiError.js';
|
||||
import { canAccessContract } from '../utils/accessControl.js';
|
||||
import { maybeActivateOnDeliveryConfirmation, withContractDocumentLock } from '../services/contractStatusScheduler.service.js';
|
||||
@@ -52,6 +52,13 @@ function sanitizeContractBody(body: unknown, parentKey?: string): unknown {
|
||||
if (parentKey && isContractIdentifierField(parentKey)) {
|
||||
return validateContractIdentifier(body, parentKey);
|
||||
}
|
||||
// Pentest 95.1/95.3/95.4 (LOW–MEDIUM, 2026-06-21): portalUsername
|
||||
// (Manual-Modus) hatte gar keine Validierung – CRLF/Header-Injection,
|
||||
// silent stripHtml-Mutation und VARCHAR-Overflow möglich. Gleiches
|
||||
// Raw-Input-Pattern wie R87.
|
||||
if (parentKey === 'portalUsername') {
|
||||
return validatePortalUsername(body, parentKey);
|
||||
}
|
||||
return stripHtml(body);
|
||||
}
|
||||
if (Array.isArray(body)) return body.map((v) => sanitizeContractBody(v, parentKey));
|
||||
|
||||
Reference in New Issue
Block a user