Grav CMS CVE-2026-42612
HIGHSeverity by source
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
Primary rating from GitHub Advisory · only source for this CVE.
CVSS VectorGitHub Advisory
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
Lifecycle Timeline
2DescriptionGitHub Advisory
Summary
A stored Cross-Site Scripting (XSS) vulnerability in getgrav/grav allows publisher-level accounts to execute arbitrary JavaScript. The issue arises from a blacklist bypass in the detectXss() function when handling unquoted HTML event attributes.
Details
The detectXss() function relies on a blacklist pattern to filter malicious attributes. The specific regex pattern used to match on* events is flawed:
'on_events' => '#(<[^>]+[a-z\x00-\x20\"\'\/])(on[a-z]+|xmlns)\s*=[\s|\'\"].*[\s|\'\"]>#iUu'This pattern fails to properly identify on* event handlers that are constructed without quotation marks. This allows an attacker to completely bypass the filter. *Note: It is highly recommended to replace this blacklist approach with a robust, established HTML sanitization library.*
PoC
An attacker with publisher-level access can reproduce this by injecting the following payload into any vulnerable content field:
<img src=x onerror=eval(atob(/YWxlcnQoZG9jdW1lbnQuY29va2llKQ/.source))><img width="1889" height="482" alt="image1" src="https://github.com/user-attachments/assets/0f1a339b-25a8-4b6e-91af-8c59e6a39297" /> <img width="3055" height="920" alt="image2" src="https://github.com/user-attachments/assets/12680058-bbb3-4446-b58e-515533bb4e90" /> <img width="2909" height="1339" alt="image3" src="https://github.com/user-attachments/assets/c7ed7e61-8dcf-402d-8589-98d18978c71a" />
Execution Details: The onerror event is written without quotes to bypass the regex. Because unquoted attributes are restricted in their character usage (e.g., the = symbol cannot be used easily), the payload leverages atob() and regex .source to decode the base64 string YWxlcnQoZG9jdW1lbnQuY29va2llKQ (which translates to alert(document.cookie)). The atob() function conveniently auto-completes the necessary = padding for the base64 string.
Impact
- Vulnerability Type: Stored Cross-Site Scripting (XSS)
- Impacted Parties: Any user (including administrators) who views the compromised content published by the attacker.
- Consequences: Attackers can execute malicious scripts in a victim's browser, leading to session hijacking (cookie theft), unauthorized actions.
---
Maintainer note - fix applied (2026-04-24)
Fixed in Grav core on the 2.0 branch: commit 5a12f9be8 - will ship in 2.0.0-beta.2.
What changed: the on_events regex in Security::detectXss() no longer requires quotes or whitespace around =. The previous form:
'on_events' => '#(<[^>]+[\s\x00-\x20\"\'\/])(on\s*[a-z]+|xmlns)\s*=[\s|\'\"].*[\s|\'\"]>#iUu'required [\s|'"] immediately after the =, so <img src=x onerror=alert(1)> slid past. The new regex drops the value-matching tail entirely and just flags the presence of an on*= attribute anywhere inside a tag:
'on_events' => '#<[^>]*?[\s\x00-\x20\"\'\/](on\s*[a-z]+|xmlns)\s*=#iu'Detecting the attribute name + = is enough for a tripwire - the trade-off is occasional false positives on legitimate attribute *values* containing on*= substrings, which the maintainer can hand-approve.
This same regex bypass was the detection-layer half of GHSA-c2q3-p4jr-c55f and GHSA-w8cg-7jcj-4vv2; the fix here knocks both down.
Files:
system/src/Grav/Common/Security.php.tests/unit/Grav/Common/Security/DetectXssTest.php- 18 cases: unquoted PoCs, quoted-form regression, safe-content negatives.
AnalysisAI
Stored cross-site scripting in Grav CMS allows publisher-level authenticated users to execute arbitrary JavaScript in victim browsers by injecting unquoted HTML event handlers that bypass the detectXss() blacklist regex. The flawed pattern failed to detect on* event attributes without surrounding quotes, enabling payloads like <img src=x onerror=eval(...)> to persist in content fields and execute when administrators or other users view the compromised page. Vendor-released patch confirmed in commit 5a12f9be8 (Grav 2.0.0-beta.2), which tightens the on_events regex to flag unquoted attributes, adds dangerous XML namespace tags (svg, math) to the default blocklist, and hardens MediaObjectTrait::attribute() with strict identifier validation. Publicly available exploit code exists. EPSS and KEV data not provided; exploitation requires publisher-level account privileges.
Technical ContextAI
Grav is a flat-file PHP content management system. The vulnerability stems from CWE-79 (Improper Neutralization of Input During Web Page Generation) in the Security::detectXss() function, which uses a regex-based blacklist to sanitize user-submitted HTML. The original on_events pattern required whitespace or quotes immediately after the = sign in event attributes, allowing unquoted syntax like onerror=alert(1) to slip through. HTML5 permits unquoted attribute values containing alphanumerics and a limited set of punctuation, which attackers exploited by encoding payloads via atob() and regex .source to work around character restrictions. The affected package is pkg:composer/getgrav_grav prior to version 2.0.0-beta.2. The commit diff shows the fix also addresses related GitHub Security Advisories (GHSA-c2q3-p4jr-c55f, GHSA-w8cg-7jcj-4vv2) by expanding the dangerous tag list and gating attribute names in MediaObjectTrait to prevent Markdown-based injection vectors. Additionally, the patch hardens SVG dimension parsing against XXE attacks and Installer::unZip against Zip Slip path traversal, indicating a comprehensive security overhaul of the 2.0 branch.
RemediationAI
Upgrade to Grav 2.0.0-beta.2 or later, which includes the fix from commit 5a12f9be8314682c8713e569e330f11805d0a663 (https://github.com/getgrav/grav/commit/5a12f9be8314682c8713e569e330f11805d0a663). The patch replaces the vulnerable on_events regex in Security::detectXss() with a stricter pattern that detects on*= attributes regardless of quoting, expands the default xss_dangerous_tags list to include svg, math, option, and select, and hardens MediaObjectTrait::attribute() to reject event handlers and other dangerous attribute names. For production systems unable to deploy a beta release, apply the commit as a manual patch to system/src/Grav/Common/Security.php and system/config/security.yaml. Compensating controls: restrict publisher role assignment to fully trusted accounts only, enable Content Security Policy headers to mitigate XSS impact (set script-src 'self' and disable 'unsafe-inline'), audit existing content for unquoted event attributes using grep/regex search for patterns like onerror=, onload=, onclick= without surrounding quotes, and configure web application firewalls to block HTML event attributes in POST bodies. Note that CSP is defense-in-depth and may break legitimate inline scripts in Grav themes; test thoroughly. If downgrading to 1.x stable, verify whether the 1.x branch received a backport of this fix via the Grav release notes.
sapi/cgi/cgi_main.c in PHP before 5.3.12 and 5.4.x before 5.4.2, when configured as a CGI script (aka php-cgi), does not
(1) boardData102.php, (2) boardData103.php, (3) boardDataJP.php, (4) boardDataNA.php, and (5) boardDataWW.php in Netgear
ProjectSend versions prior to r1720 are affected by an improper authentication vulnerability. Rated critical severity (C
Roundcube Webmail contains a critical PHP object deserialization vulnerability (CVE-2025-49113, CVSS 9.9) that allows au
Util/PHP/eval-stdin.php in PHPUnit before 4.8.28 and 5.x before 5.6.3 allows remote attackers to execute arbitrary PHP c
Palo Alto Networks PAN-OS management web interface contains an authentication bypass allowing unauthenticated attackers
Nagios XI version xi-5.7.5 is affected by OS command injection. Rated high severity (CVSS 8.8), this vulnerability is re
Nagios XI version xi-5.7.5 is affected by OS command injection. Rated high severity (CVSS 8.8), this vulnerability is re
The get_referers function in /opt/ws/bin/sblistpack in Sophos Web Appliance before 3.7.9.1 and 3.8 before 3.8.1.1 allows
The Backup Migration plugin for WordPress is vulnerable to Remote Code Execution in all versions up to, and including, 1
NetAlertX (formerly PiAlert) versions 23.01.14 through 24.x before 24.10.12 allow unauthenticated command injection thro
The GiveWP - Donation Plugin and Fundraising Platform plugin for WordPress is vulnerable to PHP Object Injection in all
Same weakness CWE-79 – Cross-site Scripting (XSS)
View allShare
External POC / Exploit Code
Leaving vuln.today
GHSA-9695-8fr9-hw5q