Validate availability slot datetimes (REST and admin form) #42

Closed
opened 2026-06-10 18:50:53 +00:00 by thatguygriff · 0 comments
Owner

Finding (security review — Low / robustness)

Both availability creation paths accept arbitrary start_dt / end_dt strings:

  • AvailabilityEndpoint::create() (src/Availability/AvailabilityEndpoint.php) — REST, sanitize_text_field only
  • AvailabilityController::addSlot() (src/Availability/AvailabilityController.php) — admin form (datetime-local inputs, Y-m-d\TH:i)

On the weekly path, new \DateTimeImmutable($startDt) in AvailabilityRepository::createWeeklySeries() throws on garbage → unhandled 500. On the single path the raw string lands in a DATETIME column and MySQL decides what to store. There is also no check that end_dt > start_dt.

Only authenticated instructors reach these paths, so this is robustness/data-integrity more than exploitability.

Fix

Normalise and validate in both paths: accept Y-m-d H:i[:s] and the datetime-local Y-m-d\TH:i[:s] variants, canonicalise to Y-m-d H:i:s, reject anything else and any slot where end <= start (REST → 400; admin form → no-op like the existing empty-field check). Cover with unit tests.

## Finding (security review — Low / robustness) Both availability creation paths accept arbitrary `start_dt` / `end_dt` strings: - `AvailabilityEndpoint::create()` (src/Availability/AvailabilityEndpoint.php) — REST, `sanitize_text_field` only - `AvailabilityController::addSlot()` (src/Availability/AvailabilityController.php) — admin form (`datetime-local` inputs, `Y-m-d\TH:i`) On the weekly path, `new \DateTimeImmutable($startDt)` in `AvailabilityRepository::createWeeklySeries()` throws on garbage → unhandled 500. On the single path the raw string lands in a DATETIME column and MySQL decides what to store. There is also no check that `end_dt > start_dt`. Only authenticated instructors reach these paths, so this is robustness/data-integrity more than exploitability. ## Fix Normalise and validate in both paths: accept `Y-m-d H:i[:s]` and the `datetime-local` `Y-m-d\TH:i[:s]` variants, canonicalise to `Y-m-d H:i:s`, reject anything else and any slot where end <= start (REST → 400; admin form → no-op like the existing empty-field check). Cover with unit tests.
thatguygriff added the bugsecurity labels 2026-06-10 18:50:53 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Unsupervised/unsupervised-scheduler#42