# phpMyFAQ has stored XSS via Utils::parseUrl() in comment rendering

Stored XSS in phpMyFAQ comment rendering: Utils::parseUrl() linkifies URLs without escaping quotes, letting a registered user inject an onmouseover handler that fires for admins.

- Payout: Research
- Severity: high
- Program: phpMyFAQ
- Found by: ericliu-12
- Disclosed: 2026-05-06
- CVE: CVE-2026-46367
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-9525-27vj-c8r8
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-9525-27vj-c8r8
- Tags: area:web domain:web impact:ato impact:data-leak kind:research platform:ghsa sev:high tech:php technique:source-review vuln:misconfiguration vuln:xss

**Target:** FAQ/News comment rendering and admin comments panel
**Root cause:** Utils::parseUrl() uses regex /(https?:\/\/[^\s]+)/i and substitutes into `<a href="$1">$1</a>` without htmlspecialchars(), so a literal `"` in the URL breaks out of the href attribute. The comment editor path uses sanitizeHtmlComment() (which preserves `"`) instead of FILTER_SANITIZE_SPECIAL_CHARS, and the template renders with `|raw`, disabling Twig auto-escaping.
**Steps:**
1. Enable main.enableCommentEditor in admin Configuration.
2. Log in as any registered user and open a FAQ entry with comments allowed.
3. Submit comment text: `https://www.evil.com/"onmouseover="alert(document.cookie)` (www. prefix required for linkification).
4. Comment is stored via sanitizeHtmlComment(), passed through parseUrl(), rendered with `{{ comment.comment|raw }}` in comment.macros.twig line 40.
5. Victim (or admin viewing /admin/content/comments) hovers the link; onmouseover fires.
**How found:** Code review of Utils::parseUrl() at Utils.php:281: noticed the regex `[^\s]+` matches `"` and `<` and that the replacement interpolates the URL into href without htmlspecialchars(). Traced the sink to the comment editor path where sanitizeHtmlComment() preserves quotes and the Twig template uses `|raw`.
**Exploitation:** Attacker with any registered account posts a crafted comment that persists and renders as `<a href="https://www.evil.com/"onmouseover="alert(document.cookie)">`. Any visitor hovering the link executes JS; targeting admins via the FAQ page or the admin comments panel yields session cookie theft and full admin account takeover. No CSP is set to mitigate.
**Escalation:** Same sink also present in admin/content/comments.twig (lines 62, 112), so admins reviewing comments are directly exposed, raising impact to admin ATO.
**Insight:** When auditing URL linkifiers, check whether the URL-matching regex excludes quote characters; `[^\s]+` does not, so any attribute-context sink without htmlspecialchars() is injectable. Also compare sanitizer paths: a feature flag that swaps FILTER_SANITIZE_SPECIAL_CHARS for a custom sanitizer often re-enables quote survival.

## Proof of concept (copied exactly from the original report)

**XSS payload submitted as comment text**

```
https://www.evil.com/"onmouseover="alert(document.cookie)
```

