Pentest 60.3 MEDIUM: sanitizePhoneField auf Customer + User-Felder ausweiten

Der Fix aus 51.3 deckte nur Contract-PhoneNumber-Felder ab. CRLF in
`Customer.phone`, `Customer.mobile` und (im selben Code-Pfad)
`User.whatsappNumber`, `User.signalNumber` ging weiter durch –
pickCustomerUpdate / pickUserUpdate macht nur stripHtml, das filtert
keine Control-Chars.

- sanitizePhoneField von contract.service nach utils/sanitize gezogen
  und EXPORT, damit alle Stellen denselben Allowlist-Check
  (/^[0-9+\-/(). ]{0,40}$/) nutzen. Literales Space, NICHT \s.
- customer.controller updateCustomer + createCustomer: phone + mobile
  durch sanitizePhoneField → 400 bei CRLF/Control-Chars.
- user.controller updateUser + createUser: whatsappNumber +
  signalNumber analog.
- contract.service nutzt jetzt den importierten Helper (Lokale
  Kopie entfernt – Single Source of Truth).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-01 22:40:40 +02:00
parent f4ac1c29db
commit 5fa9d4d4f3
4 changed files with 84 additions and 21 deletions
+1 -19
View File
@@ -2,25 +2,7 @@ import { ContractType, ContractStatus } from '@prisma/client';
import prisma from '../lib/prisma.js';
import { generateContractNumber, paginate, buildPaginationResponse } from '../utils/helpers.js';
import { encrypt, decrypt } from '../utils/encryption.js';
import { sanitizeCustomerStrict } from '../utils/sanitize.js';
// Pentest 51.3 (LOW, 2026-06-01): Telefon-/Vorwahl-Felder dürfen NIE CRLF
// oder andere Control-Chars enthalten sonst könnten sie über Header-
// Injection (Mail, HTTP) missbraucht werden, wenn der Wert mal in einen
// Header fließt (PDF/Mail-Templates, CSV-Export). Whitespace bewusst auf
// literales Space beschränkt, NICHT `\s` das matched sonst `\r\n\t`
// und macht den Schutz wirkungslos. Allowed: Ziffern, Plus, Minus, Slash,
// Klammern, Punkt, einfaches Leerzeichen. Bis 40 Zeichen.
const PHONE_FIELD_ALLOWED = /^[0-9+\-/(). ]{0,40}$/;
function sanitizePhoneField(raw: string | null | undefined, fieldLabel: string): string | undefined {
if (raw == null) return undefined;
const trimmed = String(raw).trim();
if (trimmed === '') return undefined;
if (!PHONE_FIELD_ALLOWED.test(trimmed)) {
throw new Error(`${fieldLabel} enthält unzulässige Zeichen (erlaubt sind Ziffern, +, Leerzeichen, -, /, Klammern).`);
}
return trimmed;
}
import { sanitizeCustomerStrict, sanitizePhoneField } from '../utils/sanitize.js';
export interface ContractFilters {
customerId?: number;