Allowing cancellation or rescheduling up to the moment an event starts undermines the service provider's ability to prepare: a massage therapist who learns of a cancellation 5 minutes before the appointment has no time to fill the slot, collects no revenue, and bears the full cost of the blocked time. CWE-20 applies because the handler accepts a time-based parameter (booking start time) without validating it against a business constraint. CWE-841 applies because the behavioral workflow — "changes require N hours notice" — is defined in business policy but absent from the code. Client-provided timestamps must never be used for the deadline calculation; only server-side Date.now() is trustworthy.
Medium because missing deadline enforcement causes predictable revenue loss for every last-minute cancellation, and the client cannot be trusted to enforce the policy on their own.
Compute the deadline server-side using the booking's stored startTime in your cancel and reschedule handlers (e.g., src/app/api/bookings/[id]/cancel/route.ts). Do not accept a client-provided timestamp for this comparison.
import { differenceInHours } from 'date-fns';
const hoursUntilEvent = differenceInHours(booking.startTime, new Date());
if (hoursUntilEvent < 24) {
return res.status(422).json({
code: 'CANCELLATION_WINDOW_CLOSED',
message: 'Cancellations require at least 24 hours notice.',
});
}
Apply the same check in the reschedule handler.
ID: booking-flow-lifecycle.lifecycle.deadline-enforcement
Label: Deadline enforcement for changes
Severity: medium
What to look for: Logic checking that the current time is before a cutoff (e.g., now < booking.startTime - 24 hours). Count all cancel and reschedule handlers and verify each one includes a time-based deadline check. Look for differenceInHours, Date.now(), isBefore, subHours, or manual timestamp arithmetic. Enumerate: "X of Y cancel/reschedule handlers include deadline enforcement."
Pass criteria: Code enforces a minimum notice requirement for cancellations/changes in every cancel and reschedule handler. The cutoff must be at least 1 hour before the booking start time (24 hours is standard). The check must compare the current server time against the booking start time, not a client-provided timestamp. Report: "X of Y handlers enforce [N]-hour deadline in [file:line]."
Fail criteria: Users can cancel or reschedule 1 minute before the event, or no deadline check exists in any handler. Do NOT pass when a deadline exists in the cancel handler but not in the reschedule handler (or vice versa) — both must enforce it.
Skip (N/A) when: Business policy explicitly allows last-minute changes with no restrictions (verifiable in a config file, README, or code comment stating the policy).
Detail on fail: "No time-based restriction found in the cancellation handler. Users can cancel an appointment 1 minute before it starts."
Cross-reference: The cancellation-state-machine check in this category verifies the cancellation handler where this deadline should be enforced.
Cross-reference: The modification-validation check in this category verifies the reschedule handler where this deadline should also be enforced.
Cross-reference: The refund-logic check in Payment Integration may interact with deadline policy (partial refunds for late cancellations).
Remediation: Add a deadline check in your cancel and reschedule handlers (e.g., src/app/api/bookings/[id]/cancel/route.ts).
const hoursUntilEvent = differenceInHours(booking.startTime, new Date());
if (hoursUntilEvent < 24) {
throw new Error("Cannot cancel within 24 hours of event start");
}