Stored XSS: $row['text'] rendered as raw HTML without escaping in index.php #1

Open
opened 2026-05-14 21:14:29 +02:00 by Claude · 0 comments

Problem

index.php echoes the stored text column directly as raw HTML with no additional escaping:

<?= $row['text'] ?>

The text value is Parsedown-processed HTML stored in the database. The application places full trust in Parsedown's safe mode as the only XSS barrier. If that safe mode has any bypass (well-documented for 1.7.x), or if data reaches the text column through any path other than message.php (direct DB insert, future endpoint, etc.), arbitrary JavaScript executes in every visitor's browser who views that message.

Location

index.php, line 27

Risk

Stored XSS. Any attacker who can store a crafted payload in the text column — whether by exploiting a Parsedown safe-mode bypass or via direct DB access — achieves persistent script execution in all future visitors' browsers. This enables session hijacking, credential theft, and defacement.

Suggested fix direction

  • Use htmlspecialchars() on $row['text'] when treating stored content as plain text, or — since it is intentionally stored as HTML — add a dedicated HTML sanitizer (e.g. ezyang/htmlpurifier) as a second pass before output rather than relying solely on Parsedown's safe mode.
  • Add a strict Content-Security-Policy response header to limit damage even if XSS occurs.

Severity

critical

Found by

Automated audit by Claude Code

## Problem `index.php` echoes the stored `text` column directly as raw HTML with no additional escaping: ```php <?= $row['text'] ?> ``` The `text` value is Parsedown-processed HTML stored in the database. The application places full trust in Parsedown's safe mode as the only XSS barrier. If that safe mode has any bypass (well-documented for 1.7.x), or if data reaches the `text` column through any path other than `message.php` (direct DB insert, future endpoint, etc.), arbitrary JavaScript executes in every visitor's browser who views that message. ## Location `index.php`, line 27 ## Risk Stored XSS. Any attacker who can store a crafted payload in the `text` column — whether by exploiting a Parsedown safe-mode bypass or via direct DB access — achieves persistent script execution in all future visitors' browsers. This enables session hijacking, credential theft, and defacement. ## Suggested fix direction - Use `htmlspecialchars()` on `$row['text']` when treating stored content as plain text, or — since it is intentionally stored as HTML — add a dedicated HTML sanitizer (e.g. `ezyang/htmlpurifier`) as a second pass before output rather than relying solely on Parsedown's safe mode. - Add a strict `Content-Security-Policy` response header to limit damage even if XSS occurs. ## Severity critical ## Found by Automated audit by Claude Code
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
bc1bb/OpenLongr#1
No description provided.