Jul 9, 2026·8 min read·3 visits
Authenticated path traversal in Craft CMS allows reading local SVG files and executing Stored XSS via malicious file paths.
An authenticated path traversal and arbitrary local file read vulnerability exists in Craft CMS versions 4.x up to 4.17.6 within the assets/icon endpoint and Assets helper classes. By exploiting this vulnerability, an authenticated user can traverse directories and read arbitrary .svg files on the server's filesystem, or execute Stored Cross-Site Scripting (XSS) if they can upload a malicious SVG.
This vulnerability, designated as GHSA-C43V-4CR8-6MVP, is an authenticated path traversal and local file read flaw in the content management system Craft CMS. The issue resides within the application asset management subsystem, specifically involving how the platform retrieves and processes file extensions for rendering system and custom icons. Specifically, the vulnerability manifests within the assets/icon endpoint and the associated helper methods Assets::iconPath() and Assets::iconUrl() located in the src/helpers/Assets.php component.
An authenticated user with low-level privileges can craft a specialized HTTP request containing path traversal sequences directed at the extension query parameter. Due to the lack of strict input sanitization at the boundary of the path construction utility, the application resolves paths outside the intended asset directories. If the requested target file is a valid vector graphics document, the application reads its content and returns it within the HTTP response, circumventing filesystem restrictions.
In addition to arbitrary file disclosure of graphics assets, this vulnerability poses a nested security risk by serving as an administrative entry point for Stored Cross-Site Scripting (XSS). If an attacker possesses privileges to upload file structures to any directory accessible to the web server, they can upload a malicious SVG payload and execute it by traversing to that file through the icon rendering endpoint. The resulting script execution occurs under the origin of the host application, which can facilitate administrative session hijacking.
The primary defect within Craft CMS stems from improper input validation and subsequent unsafe string concatenation in the static utility class src/helpers/Assets.php. When a client requests an icon asset via the controller action handling assets/icon, the application passes the user-controlled extension parameter directly to the helper method Assets::iconPath(). The function uses sprintf() to append this user-controlled string to the directory path returned by Craft::$app->getPath()->getAssetsIconsPath().
The system fails to perform path verification or character sanitization prior to executing standard PHP filesystem operations on the constructed path. Specifically, the method uses the PHP library function file_exists() on the unchecked string, allowing relative path traversal operators such as ../ or ..\\ to be processed natively by the operating system filesystem driver. This design pattern permits an attacker to escape the designated asset directories and reference any arbitrary location on the filesystem that is readable by the web server process.
When PHP functions such as file_exists() or fopen() receive a string path, they delegate the resolution of the path to the underlying operating system's filesystem APIs. On UNIX-like and Windows platforms, the directory separator characters and relative path tokens (. and ..) are processed iteratively. This means that when the application constructs a path containing relative sequences, the operating system resolves each segment by moving up the directory hierarchy, completely escaping the restricted boundary.
While the application did contain a regular expression validation check (preg_match('/^\w+$/', $extension)) within downstream logic, this defense was misplaced inside the fallback Assets::iconSvg() function. The fallback function is only executed when the initial path resolution via Assets::iconPath() returns false, meaning that the requested file does not exist on disk. Because the early return path in iconPath() successfully resolves existing files and bypasses the fallback logic, any target file that exists on the filesystem entirely evades this validation filter.
To understand the structural flaws, analyzing the vulnerable implementation of the helper methods within src/helpers/Assets.php is necessary. The methods iconUrl and iconPath lacked early-stage validation, allowing raw input propagation directly into filesystem checks. The following PHP code block demonstrates how the input parameter $extension was processed without validation in the vulnerable versions:
// Vulnerable Code Path in src/helpers/Assets.php
public static function iconUrl(string $extension): string
{
// User input from the query parameter is passed directly
return UrlHelper::actionUrl('assets/icon', [
'extension' => $extension,
]);
}
public static function iconPath(string $extension): string
{
// Unsanitized concatenation occurs here via sprintf
$path = sprintf('%s%s%s.svg', Craft::$app->getPath()->getAssetsIconsPath(), DIRECTORY_SEPARATOR, strtolower($extension));
// file_exists executes on the resolved path containing traversal sequences
if (file_exists($path)) {
return $path; // Early return bypasses downstream validation filters
}
...The corresponding patch implemented in version 4.17.7 inserts rigid input validation at the absolute entry points of both functions. By introducing a regular expression filter before any path manipulation or URL generation occurs, the application ensures that only safe alphanumeric strings are handled. The corrected code is shown below:
// Patched Code in src/helpers/Assets.php
public static function iconUrl(string $extension): string
{
// Restrict input strictly to alphanumeric characters and underscores
if (!preg_match('/^\w+$/', $extension)) {
throw new InvalidArgumentException("$extension isn’t a valid file extension.");
}
return UrlHelper::actionUrl('assets/icon', [
'extension' => $extension,
]);
}
public static function iconPath(string $extension): string
{
// Restrict input strictly to alphanumeric characters and underscores
if (!preg_match('/^\w+$/', $extension)) {
throw new InvalidArgumentException("$extension isn’t a valid file extension.");
}
$path = sprintf('%s%s%s.svg', Craft::$app->getPath()->getAssetsIconsPath(), DIRECTORY_SEPARATOR, strtolower($extension));
if (file_exists($path)) {
return $path;
}
...This validation design successfully mitigates the flaw by terminating execution immediately when special characters such as dots or slashes are present. Because the validation runs before the file_exists() check, the logical gap that previously allowed existing files to bypass the filter is fully closed.
Exploitation of this vulnerability requires an authenticated session with privileges sufficient to access the administrator control panel or invoke asset action controllers. An attacker can construct a payload targeting the assets/icon action by specifying a relative path in the extension query parameter. The following sequence outlines the methodology of a standard local file read attack:
To retrieve a target SVG file stored outside the designated icon directory, the attacker sends an HTTP GET request to the controller endpoint. The parameter must point to the relative location of the target file, excluding the .svg extension, as the application appends it automatically. For example, a request with extension=../../../../some_internal_resource maps to a path check for some_internal_resource.svg relative to the server webroot.
The execution of the script in the context of the browser depends on the response headers returned by the server. When the assets/icon endpoint serves the traversal target, it sets the Content-Type header to image/svg+xml. In modern web browsers, when an SVG is loaded directly as a document, embedded JavaScript is executed under the document's origin. By directing a user to the controller URL, the attacker forces a direct document load, satisfying the browser's execution conditions and enabling Stored XSS.
The impact of GHSA-C43V-4CR8-6MVP is divided into data exposure and cross-site execution vectors. While the local file read capability is restricted to files ending with the .svg extension, sensitive cryptographic keys, application configurations, or internal metadata stored in SVG formats can be disclosed. Additionally, the ability to read arbitrary SVGs can allow an attacker to reconstruct directory structures and verify the existence of specific files on the server.
The secondary risk of Stored Cross-Site Scripting (XSS) significantly elevates the severity of this vulnerability. Because the application processes and returns the SVG content directly through an administrative controller context, browser security policies render the executable scripts inside the SVG within the origin of the Craft CMS application. If an administrator triggers the rendered vector, the attacker can execute arbitrary API commands, alter system settings, or retrieve session tokens.
This vulnerability is tracked under the GitHub Security Advisory database with low-to-moderate complexity. Since the exploit does not require advanced tools or complex memory manipulation, it represents an accessible target for adversaries who have established basic authenticated access. The threat is especially relevant in shared hosting environments where file write access is distributed across multiple tenants.
Remediation of this vulnerability requires upgrading the installation of Craft CMS to version 4.17.7 or subsequent releases in the 4.x and 5.x branches. The upgrade applies the strict alphanumeric validation filter to the Assets helper, preventing the processing of path traversal sequences. Administrators should verify their current version via the composer utility or the control panel dashboard to confirm the patch is active.
If immediate patching is not feasible, administrators can apply mitigation strategies at the network and server configuration levels. Restricting access to the assets/icon action using web application firewall (WAF) rules or URL rewriting can block requests containing traversal sequences. A sample rule matching traversal patterns in the query string should be deployed to analyze incoming traffic to the controller endpoint.
Additionally, implementing strict Content Security Policy (CSP) headers can limit the execution of embedded scripts within SVG files. Specifically, setting the policy default-src 'self'; object-src 'none'; or serving user-uploaded SVGs with headers that prevent script execution helps isolate the application from XSS vectors. Regular audits of user upload directories should also be conducted to identify and purge unauthorized SVG documents containing active script tags.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Craft CMS craftcms | >= 4.0.0, <= 4.17.6 | 4.17.7 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-22 |
| Attack Vector | Network |
| CVSS Score | 6.5 (Medium) |
| EPSS Score | N/A (No CVE assigned) |
| Impact | Local File Read & Stored Cross-Site Scripting (XSS) |
| Exploit Status | Proof-of-Concept |
| KEV Status | Not Listed |
The software uses external input to construct a pathname that is intended to identify a file or directory that is located under a restricted parent directory, but the software does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
The Netty-based HTTP Client in the Micronaut framework fails to enforce a maximum redirect ceiling by default when processing HTTP responses. This permits remote, attacker-controlled servers to trigger continuous, infinite redirect loops. The resulting recursion causes high CPU utilization, thread starvation, and potential memory exhaustion, inducing a Denial of Service (DoS) state in client-side applications.
An information disclosure vulnerability exists in the Micronaut Framework's HTTP client components. The client fails to clear sensitive authorization headers and cookies when following redirects across different origins. If an application using the vulnerable client communicates with an endpoint that issues a redirect to an external host, the client will forward the original credentials, leading to potential token theft and session hijacking.
GHSA-52vm-mxx8-f227 is a dual-vector security flaw in phantom-audio (<= 1.3.0). The vulnerability allows arbitrary file writes due to unconfined Model Context Protocol (MCP) tool paths when the PHANTOM_OUTPUT_DIR environment variable is not defined. Concurrently, the platform lacks validation controls during the decompression of highly compressed audio files, resulting in resource-exhaustion denial of service and downstream parsing vulnerability exposure.
CVE-2026-56382 is a high-severity remote code execution vulnerability in Craft CMS versions 5.5.0 through 5.9.13. The vulnerability exists within the FieldsController::actionRenderCardPreview() method due to a lack of sanitization of the user-supplied fieldLayoutConfig configuration array, permitting authenticated administrators to register arbitrary PHP callbacks using Yii2 event handler injection mechanisms. This issue has been fully remediated in version 5.9.14.
An insecure direct object reference (IDOR) and missing authorization validation check in the Gittensory REST API and Model Context Protocol (MCP) server allowed authenticated users to query arbitrary miner profiles, exposing sensitive cryptographic hotkeys and daily financial/economic yields.
Code16 Sharp versions from 9.0.0 up to (but not including) 9.22.3 are vulnerable to a missing authorization flaw in the Quick Creation Command feature. The ApiEntityListQuickCreationCommandController fails to validate entity-level 'create' policies before returning administrative form designs or processing database modifications. Authenticated users with restricted access can bypass policy boundaries to access creation configurations and insert records.