GHSA-whqh-9pq5-c7r3
## Summary The `SvgSanitizer::decodeAllEntities()` method limits recursive entity decoding to 5 iterations. By wrapping each character of `javascript` in an `href` attribute value with 5 levels of `&` encoding around numeric HTML entities (e.g., `&amp;amp;amp;amp;#106;` for `j`), an attacker can bypass both `isSafe()` detection and `sanitize()` removal. The uploaded SVG is served from the application origin with `image/svg+xml` content type, and the browser's XML parser fully decodes the remaining `&#NNN;` entities, resulting in a clickable `javascript:` link that executes arbitrary JavaScript. ## Details **Root cause:** `decodeAllEntities()` at `phpmyfaq/src/phpMyFAQ/Helper/SvgSanitizer.php:223-249` limits entity decoding to `maxIterations=5`. Each iteration: (1) decodes `&#NNN;` numeric entities, (2) decodes `&#xHH;` hex entities, (3) calls `html_entity_decode()` which resolves one level of `&` → `&`. With 5 levels of `&` wrapping, all 5 iterations are consumed unwinding the `&` nesting, leaving the final `&#NNN;` numeric entities unresolved. **Code path:** 1. Authenticated user with `FAQ_EDIT` permission uploads SVG via `POST /admin/api/content/images` (`ImageController::upload()` at line 39) 2. File extension is `svg` → `SvgSanitizer::isSafe()` called (line 114) 3. `isSafe()` calls `decodeAllEntities()` — 5 iterations resolve `&` nesting but leave `ja...` (numeric entities for `javascript`) 4. Pattern matching at line 47 (`/href\s*=\s*["\'][\s]*javascript\s*:/i`) does **not** match `ja...` 5. `isSafe()` returns **true** — file saved **without any sanitization** 6. SVG served directly by web server from `content/user/images/` with `image/svg+xml` MIME type 7. Browser's XML parser decodes `j` → `j`, `a` → `a`, etc., reconstructing `javascript:alert(document.domain)` 8. User clicks the SVG link → JavaScript executes in the phpMyFAQ origin The bypass is even simpler than initially described — no `<script>` dec
Properties
- ghsa_id
- GHSA-whqh-9pq5-c7r3
- severity
- medium
- summary
- phpMyFAQ has a SVG Sanitizer Entity Decoding Depth Limit Bypass Leading to Stored XSS
- cvss_score
- 5.4
- cve_id
- GHSA-whqh-9pq5-c7r3
- cvss_vector
- CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
- is_ghsa_only
- true
- ghsa_published
- 2026-05-06T20:18:48Z
- source_url
- https://github.com/advisories/GHSA-whqh-9pq5-c7r3
- ghsa_updated
- 2026-05-06T20:18:50Z
Related Entities (6)
VULNERABLE_TO (2)
AFFECTS (2)
HAS_WEAKNESS (1)
REPORTED_BY (1)
Explore deeper with Ninja Signal's threat intelligence graph