Executive Summary
A path traversal vulnerability in Grav CMS's MediaUploadTrait::deleteFile() allows authenticated users with media management permissions to delete arbitrary files on the server. This vulnerability has a CVSS score of 7.1 and is classified as CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal'). The vulnerability is reachable through the Flex media handling pipeline and requires an authenticated admin user with page/media editing permissions.
Technical Analysis
The vulnerability is caused by the `deleteFile()` method in `MediaUploadTrait.php` only validating the basename portion of the filename using `Utils::checkFilename()`, while the directory path is preserved and passed unvalidated to `unlink()`. This enables directory escape from the intended media storage path. The vulnerability is classified as CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
How It Gets Exploited
An attacker with authenticated admin user with page/media editing permissions can exploit this vulnerability by submitting a Flex object form with a crafted media deletion where the filename key contains path traversal. For example, an attacker can create a target file and then submit a form with a filename key that contains path traversal sequences, such as `../../data/target.txt`. The `deleteFile()` method will then delete the file outside the intended media directory.
Impact Assessment
The impact of this vulnerability is high, with a CVSS score of 7.1. An attacker can delete arbitrary files on the server, including configuration files, page content files, authentication-related files, and critical application files. This can lead to denial of service, privilege escalation, and potentially allow an attacker to gain control of the server.
Recommended Actions
To mitigate this vulnerability, users should update the `MediaUploadTrait.php` file to validate the full filename, not just the basename, using `Utils::checkFilename()`. The fix involves applying the following code change:
```php
public function deleteFile(string $filename, ?array $settings = null): void
{
$settings = $this->getUploadSettings($settings);
$filesystem = Filesystem::getInstance(false);
// Validate the FULL filename, not just the basename
if (!Utils::checkFilename($filename)) {
throw new RuntimeException(/* ... */);
}
// ... rest unchanged
}
```
Additionally, users should also apply the same fix to the `renameFile()` method for both `$from` and `$to` parameters.
Sources
- GitHub Security Advisories
- CVE-2026-72695