CVE-2026-74907: Grav CMS Unauthenticated Path Traversal via plugin-asset-map.php
A missing directory-boundary check in Grav's fast static asset server lets unauthenticated attackers read files from sibling directories that were never meant to be public, with no login required.
The problem
Grav's top-level index.php includes a fast-path static asset server that fires before the CMS even boots. It is gated on the presence of user/config/plugin-asset-map.php, an opt-in file created by plugins that bundle single-page apps.
When that file exists, any HTTP request is handled with no authentication check at all. The containment test that was supposed to keep responses inside the published asset directory was broken, letting attackers escape into unintended sibling directories.
Proof of concept
A working proof-of-concept for CVE-2026-74907 in getgrav/grav, with the exact payload below.
GET /myplugin-assets/../assets-secret/config.php HTTP/1.1
Host: target.example.comThe vulnerable code resolves the requested path with realpath() (so classic ../../etc/passwd traversals are blocked) and then checks str_starts_with($realFile, $realBase). That is a plain string-prefix test with no separator awareness. A directory named assets-secret sitting next to the configured assets base will pass the check because the string assets-secret/... literally starts with assets.
The patch appends DIRECTORY_SEPARATOR before the comparison, changing it to str_starts_with($realFile, $realBase . DIRECTORY_SEPARATOR). This forces the match to end exactly at a directory boundary, making the assets-secret escape impossible. The fix is in commit d5f89d95d94cc155bc3be998ee85527a7be073dd and shipped in Grav 2.0.15.
The fix
Upgrade getgrav/grav to 2.0.15 or later. If you cannot upgrade immediately, either remove user/config/plugin-asset-map.php (disabling the fast-path entirely) or add a web-server rule that blocks traversal sequences (../) in the URL path before PHP is reached.
Reported by alham-rizvi.
Related research
- high · 8.1CVE-2026-72695CVE-2026-72695: Grav CMS Path Traversal in MediaUploadTrait::deleteFile() Allows Arbitrary File Deletion
- highCVE-2026-69089CVE-2026-69089: Grav CMS Path Traversal via ImageMedium::watermark()
- high · 7.7CVE-2026-76839CVE-2026-76839: Grav CMS Twig Sandbox Credential Leak via offsetGet()
- critical · 8.8CVE-2026-75827CVE-2026-75827: Grav CMS Arbitrary File Write via Blueprint error_log Injection