Same-day cutoff rules applied server-side at booking creation
Why it matters
Same-day cutoff rules that live only in the slot-filter query are display controls, not booking controls. A direct POST to the booking API bypasses the hidden slots entirely. OWASP A03 (Injection) and CWE-20 (Improper Input Validation) apply whenever a server accepts client-supplied timestamps without verifying them against business rules. Without server-side cutoff enforcement, a customer can schedule a same-day appointment that the host has no time to prepare for, or an automated client can flood the schedule with last-minute bookings.
Severity rationale
High because the gap between UI slot-filtering and API validation means any direct API caller can book inside the cutoff window, bypassing the host's advance-notice requirement entirely.
Remediation
Add a cutoff constant and validate it against the request timestamp at the booking API handler, not only when generating the list of available slots.
// src/app/api/book/route.ts
const ADVANCE_BOOKING_HOURS = 24
export async function POST(req: Request) {
const { startTime } = await req.json()
const requested = new Date(startTime)
const earliest = new Date(Date.now() + ADVANCE_BOOKING_HOURS * 3_600_000)
if (requested < earliest) {
return Response.json(
{
error: 'Too soon',
detail: `Bookings require at least ${ADVANCE_BOOKING_HOURS}h notice`,
},
{ status: 400 }
)
}
// ... create booking
}
Co-locate this check with duration and buffer validation so all server-side time boundaries are auditable in one place.
Detection
-
ID:
same-day-cutoff -
Severity:
high -
What to look for: Search for advance booking cutoff configuration (e.g.,
ADVANCE_BOOKING_HOURS = 24,MIN_NOTICE_HOURS,cutoffHours). Count all booking creation API endpoints. For each, verify the server compares the requested time againstnow + cutoffand rejects requests that violate the rule. Check if this validation is in the API route handler or only in the calendar UI filter. Examine files matchingsrc/app/api/book*/route.ts,src/app/api/appointment*/route.ts,src/lib/*booking*,src/lib/*config*. -
Pass criteria: Count all booking API endpoints. At least 1 advance booking cutoff constant must be defined server-side (e.g.,
ADVANCE_BOOKING_HOURS). 100% of booking creation endpoints must comparerequestedTimeagainstnow + cutoffHoursand return HTTP 400/409 when violated. Report: "Cutoff hours: [value]. X of Y endpoints enforce server-side." -
Fail criteria: Cutoff is only applied when filtering available slots for display, not when validating a booking request. Or no cutoff constant exists in server-side code.
-
Skip (N/A) when: Platform explicitly does not enforce advance booking cutoffs (accepts last-minute bookings by design).
-
Detail on fail: Example:
"Calendar hides same-day slots, but API does not check. A direct POST with a same-day time succeeds." -
Cross-reference: Check
duration-validation— cutoff and duration validations should be co-located in the same API middleware. -
Cross-reference: Check
advance-booking-limits— same-day cutoff guards the near end; advance limits guard the far end. -
Cross-reference: Check
past-date-protection— client-side past-date guard complements server-side cutoff validation. -
Remediation: Validate cutoff server-side:
// pages/api/appointments.ts const ADVANCE_BOOKING_HOURS = 24 export async function POST(req: Request) { const { startTime } = await req.json() const now = new Date() const requestedTime = new Date(startTime) const minimumAllowedTime = new Date( now.getTime() + ADVANCE_BOOKING_HOURS * 60 * 60 * 1000 ) if (requestedTime < minimumAllowedTime) { return Response.json( { error: 'Too late to book', detail: `Bookings must be made at least ${ADVANCE_BOOKING_HOURS} hours in advance`, }, { status: 400 } ) } // ... create booking }
External references
- cwe · CWE-20 — Improper Input Validation — same-day cutoff not enforced server-side
- owasp:2021 · A03 — Injection — booking time constraints bypassed via direct API call
Taxons
History
- 2026-04-18·v1.0.0·Initial import from booking-calendar-availability·automated