Security hardening: booking auth, offering exposure, payments, invites (#31–#37) #38
Reference in New Issue
Block a user
Delete Branch "feature/security-fixes"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Security fixes from a pen-test review of the plugin's access control, injection surface, and information/payment-data exposure. Closes #31, #32, #33, #34, #35, #36, #37.
The SQL layer (parameterized throughout) and output escaping were already sound; these changes address logic-level authorization gaps, a disclosure surface, a booking race, and a couple of hardening items.
Changes
BookingEndpoint::book()no longer trusts a clientoffering_id: a slot-tied offering is authoritative, and any offering used must belong to the slot's instructor — closing a free/misrouted-payment bypass.offerings,offerings/{id}/questions, andpoliciesread endpoints now requirebook_lessoninstead of__return_true(no anonymous consumer exists).Offering::toArray()also omitsetransfer_emailfrom listings as defense-in-depth.UPDATE … WHERE is_booked = 0) before a lesson is inserted, preventing a double-booking / double-charge race.MAX_WEEKLY_OCCURRENCES = 12) and only creates lessons for slots it actually claimed.Invite::isAcceptable), enforced at registration and surfaced on the admin invites list.Notes
AvailabilityEndpointnow takes anOfferingRepository(wired inRestRegistrar)./payments/webhookendpoint remains__return_trueby design — it is signature-verified and called server-to-server by Stripe, which has no WP session.createIntentresponse for their own registration.Tests
Adds
BookingEndpointTest(offering-substitution rejection, claim/409 race, happy path) plusInvite,Offering, andAvailabilityRepositorycoverage, and minimalWP_REST_Request/WP_REST_Responsestubs to the test bootstrap.composer test(200 tests, 572 assertions),composer lint(PHPStan L6),composer cs(PHPCS) all green.🤖 Generated with Claude Code
5140e76347to061d09e034