Without server-side contact field validation, malformed data reaches the database: null bytes in email fields break transactional email delivery, invalid phone numbers fail SMS delivery, and a booking with a corrupt contact record becomes impossible to reach for reminders or cancellations. OWASP A03 (Injection) covers malicious input reaching persistence; CWE-20 covers missing input validation generally. A booking where the customer cannot be contacted is, from an operational standpoint, as bad as a booking that was never created — except the slot is now blocked.
Medium because storing invalid contact data silently breaks the notification pipeline for every affected booking, causing operational failures without surfacing an error to the developer.
Run schema validation in the API route or server action (e.g., src/app/api/bookings/route.ts), not in the client component. Never rely on browser-side form validation for data that persists to the database.
import { z } from 'zod';
const BookingSchema = z.object({
email: z.string().email(),
phone: z.string().min(10).max(15).regex(/^\d+$/),
firstName: z.string().min(1).max(100),
lastName: z.string().min(1).max(100),
});
const parsed = BookingSchema.safeParse(req.body);
if (!parsed.success) return res.status(422).json({ errors: parsed.error.issues });
ID: booking-flow-lifecycle.booking-creation.customer-contact
Label: Customer contact validation
Severity: medium
What to look for: Validation logic for email and phone number in the booking creation payload. This must be server-side validation using a schema validator (Zod, Joi, Yup, class-validator) or explicit regex. Count all input fields in the booking creation schema and verify each contact field has validation rules. Check both the API handler and any shared validation schema file (e.g., src/lib/validations/booking.ts).
Pass criteria: Server-side validation ensures email format is valid (RFC 5322 or equivalent library check) and phone format meets requirements (at least 10 digits, no more than 15) before saving to database. At least 2 contact fields (email + phone or email + name) must have explicit validation rules. Report: "X of Y contact fields have server-side validation in [file]."
Fail criteria: No server-side validation (only frontend validation in a React component), or validation is missing entirely, or invalid formats are stored. Do NOT pass when validation exists only in a client-side form component (e.g., use client file with z.object) but is absent from the API route or server action handler.
Skip (N/A) when: User contact info is pre-filled from an authenticated profile and the booking creation handler reads contact data exclusively from the authenticated session (never from request body).
Detail on fail: "No server-side validation for email field in createBooking. Invalid formats like 'notanemail' can be stored."
Cross-reference: The initial-booking-state check in this category verifies the booking record structure that includes these contact fields.
Cross-reference: The modification-validation check in Lifecycle Management verifies that contact updates during rescheduling also validate.
Cross-reference: The status-updates check in Lifecycle Management verifies notifications are sent to these validated contact fields.
Remediation: Use a schema validator in your API handler or server action (e.g., src/app/api/bookings/route.ts or src/lib/validations/booking.ts).
const schema = z.object({
email: z.string().email(),
phone: z.string().min(10).max(15).regex(/^\d+$/),
firstName: z.string().min(1),
lastName: z.string().min(1),
});
const validated = schema.parse(req.body);
const booking = await db.booking.create({ data: validated });