CVE-2026-64851
Security::detectXss() doesn't fail—it was never designed to succeed against this attack surface. That's the critical insight this CVE exposes. The bypass works because shortcodes use bracket syntax [], not angle brackets. Security::detectXss() validates input at the HTML layer (looking for literal '<' characters), but shortcodes are a domain-specific language that gets interpreted downstream. The check passes because '[onclick=alert(1)]' contains no angle brackets—yet when ColorShortcode.php or its attribute handlers render output, they concatenate the shortcode parameter directly into an HTML attribute without encoding. Event handlers like onerror, onload, and onmouseover execute without any '<' requirement. The function wasn't bypassed; it was validating at the wrong layer of interpretation entirely. The privilege escalation dimension is what makes this severe. The admin.pages permission requirement doesn't mitigate the vulnerability—it selects for the threat actors most likely to exploit it. A single compromised admin account can inject one malicious shortcode into a page template, and that payload executes against every visitor to every page that includes it. Because the shortcode renders in the admin panel itself, subsequent administrators viewing any affected page get their sessions compromised. One medium-privilege account becomes persistent, site-wide execution. That's lateral movement, not a drive-by exploit. The fix in Grav 6.2.2 (output encoding at the rendering layer) addresses the immediate vulnerability but leaves a deeper architectural question unresolved: Security::detectXss() creates a false confidence boundary across the codebase. Any third-party shortcode plugin that uses this function as its security checkpoint is inheriting the same false guarantee. If you're auditing Grav shortcode plugins, treat 'passed detectXss' as a starting point for scrutiny, not a security closure. The pattern of a Security-prefixed function validating against script-tag injection while missing attribute-based vectors has recurred across three eras of web security—it's a known failure mode that this CVE demonstrates is alive in modern plugin ecosystems.
Reviewed through automated stages and approved by a human before publication.