Sanitize policy bodies at output in PolicyEndpoint::index (defense-in-depth) #40

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

Finding (security review — Low, defense-in-depth)

assets/js/booking.js and assets/js/group-classes.js inject the policy body from GET /policies into innerHTML unescaped, and PolicyEndpoint::index() (src/Policy/PolicyEndpoint.php) returns the stored body verbatim.

Safety currently rests entirely on wp_kses_post being applied on every write path — which it is today (REST addVersion/updateVersion and the admin PolicyController) — but any future write path that forgets it becomes stored XSS served to every student in the booking/enrolment flow.

The server-rendered registration template already applies wp_kses_post at output (templates/frontend/register-page.php); the REST listing should match.

Fix

Run the body through wp_kses_post() in PolicyEndpoint::index() before returning it. Update the endpoint unit test.

## Finding (security review — Low, defense-in-depth) `assets/js/booking.js` and `assets/js/group-classes.js` inject the policy `body` from `GET /policies` into `innerHTML` unescaped, and `PolicyEndpoint::index()` (src/Policy/PolicyEndpoint.php) returns the stored body verbatim. Safety currently rests entirely on `wp_kses_post` being applied on every write path — which it is today (REST `addVersion`/`updateVersion` and the admin `PolicyController`) — but any future write path that forgets it becomes stored XSS served to every student in the booking/enrolment flow. The server-rendered registration template already applies `wp_kses_post` at output (templates/frontend/register-page.php); the REST listing should match. ## Fix Run the body through `wp_kses_post()` in `PolicyEndpoint::index()` before returning it. Update the endpoint unit test.
thatguygriff added the security label 2026-06-10 18:50:52 +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#40