Grav CMS, Stored XSS via Unpaired Quote Bypass in detectXss(), CVE-2026-75828 (High) -DC-Sep2026-2466

Listen to this Post

The vulnerability exists in the `Security::detectXss()` function of Grav CMS, specifically in the `on_events` regex used to detect event-handler attributes in saved content. The regex was hardened in GHSA-269c to treat a `>` inside a quoted attribute value as data rather than a tag close, making the scan quote-aware. However, this same quote-awareness introduced a new bypass: the regex treats any `”` or `’` as a string delimiter, while the HTML tokenizer only enters a quoted-value state when a quote appears immediately after =. An unpaired quote inside an unquoted attribute value is, to the browser, just a value character, but to the regex it is an unterminated string that neither `[^>”‘]` nor `”[^”]”` can consume. The lazy tag-body scan therefore cannot advance past the unpaired quote to reach a following `on…=` handler. No alignment matches occur and `detectXss()` returns null, allowing the payload to be stored verbatim. When page content is rendered through `{{ page.content|raw }}` and raw inline HTML passes Parsedown by default (markdown.escape_markup: false), the event handler executes in the site origin for every visitor. An authenticated content editor with page/form edit rights but without `admin.super` can exploit this. The same detector core also backs Security::detectXssInEditorContent(), the `detectXssFromPages()` admin scanner, and the `xss()` Twig function, so all of them report the payload clean. The flaw affects Grav versions before 2.0.15 and is distinct from GHSA-269c, which addressed a different quote-parsing discrepancy.

DailyCVE Form:

Platform: Grav CMS
Version: 2.0.13
Vulnerability: Stored XSS
Severity: High
date: 2026-08-03

Prediction: 2026-09-17

What Undercode Say

Vulnerable detector core
system/src/Grav/Common/Security.php:290
Regex pattern
<(?:"[^"]"|'[^']'|[^>"'])?(?:[\s\x00-\x20"'/]|"[^"]"|'[^']')on\s[a-z]+\s=iu
Run via patternMatches() at :315-330
// Sole save-time guard for non-super content
Validation::checkSafety() // system/src/Grav/Common/Data/Validation.php:160 scalars, :165 arrays
// Invoked per field from
BlueprintSchema::validate -> Validation::checkSafety // system/src/Grav/Common/Data/BlueprintSchema.php:248
// xss_whitelist: [admin.super] exempts only super-admins (Validation.php:148)

Exploit: (Educational Purposes!)

<!-- Baseline: blocked -->
<img src=x onerror=alert(1)>
<!-- GHSA-269c payload: blocked (prior fix works) -->
<img src=x =">" onerror=alert(1)>
<!-- BYPASS A: passes (no XSS detected) -->
<img src=x" onerror=alert(1)>
<!-- BYPASS B: passes -->
<img =x" onerror=alert(1)>
<!-- BYPASS C: passes -->
<a href=x" onmouseover=alert(1)>x</a>
<!-- BYPASS D: passes -->
<img src=x' onerror=alert(1)>
<!-- BYPASS E: passes -->
<div id=x" onmouseover=alert(1)>hover</div>

Protection: from this CVE

Recommended fix: update to Grav 2.0.15 or later
Alternative: modify the on_events regex to treat a quote as a delimiter
only in the after-= position, or normalize unquoted attribute values
before the handler scan.
Additional mitigation: encode " and ' in stored non-super content,
or default markdown.escape_markup: true for non-super authors.

Impact:

CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N (8.7). A non-super editor account can store a payload that executes script in the site origin against every visitor, including administrators viewing the content. The image `src` 404s and `onerror` fires automatically, requiring no user interaction beyond rendering the page. Other rules do not cover the payload because img/a/div are not in xss_dangerous_tags, and there is no javascript:/data: scheme or style/url/expression attribute.

🎯Let’s Practice Exploiting & Learn Patching For Free:

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top