CVE-2026-42608: Getgrav/grav Path Traversal Vulnerability

HIGH
Advisory Identifier: GHSA-hmcx-ch82-3fv2
CWE-22
Published
Advisory Summary

CVE-2026-42608 is a HIGH path traversal vulnerability (CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')) affecting Getgrav/grav libraries in the Packagist ecosystem. The issue involves grav has unauthenticated path traversal & arbitrary file write in its formflash component. Remediation is available by upgrading affected packages to version 2.0.0-beta.2.

CVE-2026-42608 at a Glance

CVE Identifier CVE-2026-42608
GHSA Identifier GHSA-hmcx-ch82-3fv2
Severity HIGH
CVSS v3.1 Base Score N/A
CWE Classification CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
Affected Product Getgrav/grav
Package Ecosystem Packagist
Published Date
Last Updated

How to Fix CVE-2026-42608

To remediate this vulnerability, upgrade all affected Getgrav/grav dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

getgrav/grav fixed: 2.0.0-beta.2
Upgrade getgrav/grav to 2.0.0-beta.2
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for getgrav/grav

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-42608, inspect your project dependencies for Getgrav/grav:

inspect dependencies for getgrav/grav

Analyze the terminal output to locate any version of Getgrav/grav in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 2.0.0-beta.2), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal'), where the product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product 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. In Getgrav/grav, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

# Vulnerability Report: Grav CMS Unauthenticated Path Traversal & Arbitrary File Write **[ZERO-DAY] Unauthenticated Path Traversal leading to Arbitrary Directory Creation and Configuration Injection** ## Summary 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. ## Affected Component - Versions: Confirmed in Grav v1.7.49.5 (latest stable) and the latest development source (March 2026). - Class: `Grav\Framework\Form\FormFlash` - Method: `__construct()` / `getTmpDir()` - Parameter: `session_id` (Mapped to `__form-flash-id` in POST requests) ## Vulnerability Details 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: ```php $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/`). ## Affected Versions & Zero-Day Status - Tested Version: v1.7.49.5 (Latest Stable Release as of Nov 2025). - Development Branch Status: Vulnerable. The latest source code in the GitHub develop branch (March 2026) remains unpatched. - Affected Range: All Grav CMS versions utilizing the FormFlash component (v1.7.x and potentially older v1.6.x versions). - CVE Status: Zero-Day (Non-Registered). Extensive research confirmed no existing CVE addresses this specific core FormFlash session-based traversal. ## Steps to Reproduce 1. Identify any page containing a Grav Form (e.g., `/contact`). 2. Intercept the POST request during form submission. 3. Modify the `__form-flash-id` parameter to include a traversal sequence targeting a writable directory (e.g., `../../user/config/proof_dir`). 4. Submit the request. 5. Observe that a new directory (`poc/`) and file (`index.yaml`) have been created at the traversed path. ## Request Example ```http 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 ``` ## Response / Result - HTTP/1.1 302 Found (Standard redirect) - Filesystem Modification: - Directory Created: `/var/www/html/user/config/proof_dir/poc/` - File Created: `/var/www/html/user/config/proof_dir/poc/index.yaml` ## Proof of Concept Evidence (Before/After) ### Before Exploitation - Status: Directory does not exist. - Evidence: ```bash $ ls -la /var/www/html/user/config/proof_dir/ ls: cannot access '/var/www/html/user/config/proof_dir/': No such file or directory ``` ### After Exploitation - Status: Arbitrary directory and `index.yaml` created. - Evidence: ```bash $ 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 ``` ## Impact - Clarified Cross-User Attack: By controlling the session identifier, an attacker can overwrite or interfere with other users temporary form data, breaking session isolation. - Configuration Injection: Writing `index.yaml` into plugin/theme configuration subdirectories can alter application behavior or inject malicious settings. - Data Integrity: Unauthorized modification of configuration subfolders can lead to widespread site corruption or logical bypasses. - Denial of Service (DoS): Recursive directory creation enables attackers to exhaust disk space or inodes (inode exhaustion). ## Attack Requirements - Authentication: None (Unauthenticated) - Configuration: Standard Grav installation with at least one form-enabled page (e.g., Contact, Login, Registration) ## Exploitability Assessment - Complexity: Low. Requires only basic HTTP POST parameters. - Reliability: 100% (Deterministically reproducible in vulnerable versions). - Severity: Critical / High. The vulnerability requires no authentication and allows filesystem manipulation and session data corruption. ## Remediation 1. Sanitize Session IDs: Apply `basename()` or a strict alphanumeric regex to the `session_id` in FormFlash before path construction. 2. Filesystem Hardening: Ensure `user/config/` and other sensitive directories have restrictive permissions preventing the webserver from creating new subdirectories. 3. Update Grav: Monitor for patches addressing FormFlash sanitization. --- ## Maintainer note — fix applied (2026-04-24) Fixed in Grav core on the `2.0` branch: commit [`d904efc33`](https://github.com/getgrav/grav/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.php`](https://github.com/getgrav/grav/blob/2.0/system/src/Grav/Framework/Form/FormFlash.php) - [`tests/unit/Grav/Common/Security/FormFlashSecurityTest.php`](https://github.com/getgrav/grav/blob/2.0/tests/unit/Grav/Common/Security/FormFlashSecurityTest.php) — 32 test cases covering the PoC + variants.

CVE-2026-42608 Affected Getgrav/grav Versions

1 component(s)
Fixed Versions:
2.0.0-beta.2
Product / Package Ecosystem Affected Versions Fixed Version
getgrav/grav
Packagist
< 2.0.0-beta.2
2.0.0-beta.2

References

Frequently Asked Questions

What is CVE-2026-42608?
CVE-2026-42608 is a security vulnerability in Getgrav/grav involving Grav has Unauthenticated Path Traversal & Arbitrary File Write in its FormFlash component under CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
Which Getgrav/grav versions are affected?
Affected versions include releases prior to 2.0.0-beta.2 across affected packages: getgrav/grav.
What version fixes CVE-2026-42608?
Upgrading to 2.0.0-beta.2 (or the latest patched release for your respective branch) resolves the vulnerability.
Is getgrav/grav affected?
Yes, getgrav/grav is affected in releases prior to 2.0.0-beta.2. Upgrade your dependency to 2.0.0-beta.2 or later.
What CWE is associated with CVE-2026-42608?
CVE-2026-42608 is classified under CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') (The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product 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.).
How can I check Packagist dependencies for CVE-2026-42608?
Run the dependency tree command: 'inspect dependencies for getgrav/grav'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-hmcx-ch82-3fv2",
  "modified" : "2026-05-13T13:52:35Z",
  "published" : "2026-05-05T21:34:58Z",
  "aliases" : [ "CVE-2026-42608" ],
  "summary" : "Grav has Unauthenticated Path Traversal & Arbitrary File Write in its FormFlash component",
  "details" : "# Vulnerability Report: Grav CMS Unauthenticated Path Traversal & Arbitrary File Write\n\n**[ZERO-DAY] Unauthenticated Path Traversal leading to Arbitrary Directory Creation and Configuration Injection**\n\n## Summary\n\nGrav 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.\n\nThis vulnerability can lead to unauthorized modification of application behavior, potential data integrity issues, and service disruption in production environments.\n\n## Affected Component\n\n- Versions: Confirmed in Grav v1.7.49.5 (latest stable) and the latest development source (March 2026).\n- Class: `Grav\\Framework\\Form\\FormFlash`\n- Method: `__construct()` / `getTmpDir()`\n- Parameter: `session_id` (Mapped to `__form-flash-id` in POST requests)\n\n## Vulnerability Details\n\nThe 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:\n\n```php\n$folder = $config['folder'] ?? ($this->sessionId ? 'tmp://forms/' . $this->sessionId : '');\n$this->folder = $folder && $locator->isStream($folder) ? $locator->findResource($folder, true, true) : $folder;\n```\n\nLack 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/`).\n\n## Affected Versions & Zero-Day Status\n\n- Tested Version: v1.7.49.5 (Latest Stable Release as of Nov 2025).\n- Development Branch Status: Vulnerable. The latest source code in the GitHub develop branch (March 2026) remains unpatched.\n- Affected Range: All Grav CMS versions utilizing the FormFlash component (v1.7.x and potentially older v1.6.x versions).\n- CVE Status: Zero-Day (Non-Registered). Extensive research confirmed no existing CVE addresses this specific core FormFlash session-based traversal.\n\n## Steps to Reproduce\n\n1. Identify any page containing a Grav Form (e.g., `/contact`).\n2. Intercept the POST request during form submission.\n3. Modify the `__form-flash-id` parameter to include a traversal sequence targeting a writable directory (e.g., `../../user/config/proof_dir`).\n4. Submit the request.\n5. Observe that a new directory (`poc/`) and file (`index.yaml`) have been created at the traversed path.\n\n## Request Example\n\n```http\nPOST /contact HTTP/1.1\nHost: target.grav.cms\nContent-Type: application/x-www-form-urlencoded\n\n__form-name-=contact&__form-flash-id=../../user/config/proof_dir&form-data[name]=Attack&form-data[message]=Payload\n```\n\n## Response / Result\n\n- HTTP/1.1 302 Found (Standard redirect)\n- Filesystem Modification:\n  - Directory Created: `/var/www/html/user/config/proof_dir/poc/`\n  - File Created: `/var/www/html/user/config/proof_dir/poc/index.yaml`\n\n## Proof of Concept Evidence (Before/After)\n\n### Before Exploitation\n\n- Status: Directory does not exist.\n- Evidence:\n\n```bash\n$ ls -la /var/www/html/user/config/proof_dir/\nls: cannot access '/var/www/html/user/config/proof_dir/': No such file or directory\n```\n\n### After Exploitation\n\n- Status: Arbitrary directory and `index.yaml` created.\n- Evidence:\n\n```bash\n$ ls -la /var/www/html/user/config/proof_dir/poc/index.yaml\n-rw-rw-r-- 1 www-data www-data 158 Mar 23 22:15 /var/www/html/user/config/proof_dir/poc/index.yaml\n$ cat /var/www/html/user/config/proof_dir/poc/index.yaml\nform: ''\nid: ''\nunique_id: poc\n...\ndata:\n  poc_status: confirmed\n```\n\n## Impact\n\n- Clarified Cross-User Attack: By controlling the session identifier, an attacker can overwrite or interfere with other users temporary form data, breaking session isolation.\n- Configuration Injection: Writing `index.yaml` into plugin/theme configuration subdirectories can alter application behavior or inject malicious settings.\n- Data Integrity: Unauthorized modification of configuration subfolders can lead to widespread site corruption or logical bypasses.\n- Denial of Service (DoS): Recursive directory creation enables attackers to exhaust disk space or inodes (inode exhaustion).\n\n## Attack Requirements\n\n- Authentication: None (Unauthenticated)\n- Configuration: Standard Grav installation with at least one form-enabled page (e.g., Contact, Login, Registration)\n\n## Exploitability Assessment\n\n- Complexity: Low. Requires only basic HTTP POST parameters.\n- Reliability: 100% (Deterministically reproducible in vulnerable versions).\n- Severity: Critical / High. The vulnerability requires no authentication and allows filesystem manipulation and session data corruption.\n\n## Remediation\n\n1. Sanitize Session IDs: Apply `basename()` or a strict alphanumeric regex to the `session_id` in FormFlash before path construction.\n2. Filesystem Hardening: Ensure `user/config/` and other sensitive directories have restrictive permissions preventing the webserver from creating new subdirectories.\n3. Update Grav: Monitor for patches addressing FormFlash sanitization.\n\n---\n\n## Maintainer note — fix applied (2026-04-24)\n\nFixed in Grav core on the `2.0` branch: commit [`d904efc33`](https://github.com/getgrav/grav/commit/d904efc33) — will ship in **2.0.0-beta.2**.\n\n**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.\n\n**Files:**\n\n- [`system/src/Grav/Framework/Form/FormFlash.php`](https://github.com/getgrav/grav/blob/2.0/system/src/Grav/Framework/Form/FormFlash.php)\n- [`tests/unit/Grav/Common/Security/FormFlashSecurityTest.php`](https://github.com/getgrav/grav/blob/2.0/tests/unit/Grav/Common/Security/FormFlashSecurityTest.php) — 32 test cases covering the PoC + variants.",
  "severity" : [ {
    "type" : "CVSS_V4",
    "score" : "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/E:P"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Packagist",
      "name" : "getgrav/grav"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "2.0.0-beta.2"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/getgrav/grav/security/advisories/GHSA-hmcx-ch82-3fv2"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-42608"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/getgrav/grav/commit/c66dfeb5ff679a1667678c6335eb9ff3255dfc47"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/getgrav/grav/commit/d904efc33e03ebb597afde8d3368b28cf0423632"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/getgrav/grav"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-22" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-05-05T21:34:58Z",
    "nvd_published_at" : "2026-05-11T16:17:33Z"
  }
}