Security release. Operators running 0.3.0 or earlier should upgrade.
If you cannot upgrade immediately, restrict GET /api/reservations/:id at the
reverse proxy. Note that the storefront uses this endpoint to render a customer's
own booking detail, so blocking it outright will break that view.
GET /api/reservations/my-reservations is correctly scoped to the caller and is
unaffected.
Security
Broken access control on GET /api/reservations/:id
- The endpoint was authenticated but performed no ownership or role check, so any signed-in customer could read any reservation in the deployment by its ID, including the booking customer's name, e-mail address, phone number, private comment, date, time, party size, table and location.
getReservationnow returns403 Access deniedunless the caller is staff or the reservation's own customer, matching the check already applied to orders.- Affects all releases up to and including 0.3.0. Introduced in 80730d0, which predates 0.1.0.
- Exploitation requires knowing a reservation ID. These are
cuid()values and are not practically enumerable, so an attacker would need to obtain one from a shared link, referrer header, log or integration. - Same defect class as the order IDOR fixed in #43; that change covered
order.controller.tsandsettings.controller.tsbut notreservation.controller.ts. - Tracked as GHSA-2w4m-hjg2-2v92. CVSS 3.1 4.3 (Medium),
AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N. CWE-639. - Reported privately by Nirut Tangprasitti (SOSECURE Co., Ltd.).
Fixed
POST /api/reservationsnow returns400instead of a500when called with a staff token.createReservationreaduser.idwithout checkingtype === 'customer', so a staffUser.idwas written into theReservation.customerIdforeign key toCustomer.idand failed at the database layer. Matches the checkcreateOrderalready carried
Changed
- Updated the supported-versions table in
SECURITY.md: added 0.3.x, which was missing after 0.3.0 shipped, and dropped 0.1.x to unsupported. Security fixes are backported to 0.2.x and later only
Docs
packages/docs/api/reservations.md: added the missing "Get reservation" row to the permissions summary, and documented the ownership rule on the endpoint itself. Its snippet previously showed a bare<token>where every neighbouring endpoint specified the principal
Tests
- Added regression coverage for
GET /api/reservations/:id: unauthenticated access, owning customer, cross-customer access, and staff access - Added
reservation-idor.regression.test.ts, contributed by the reporter: 12 cases pinning object-level authorization on reservations, asserting that the denied response contains none of the owner's e-mail, phone or comment across both the raw text and the parsed body, plus two characterization cases forGET /api/orders/:id, whose #43 guard previously had no test of its own