GHSA-HMCX-CH82-3FV2

Vulnerability from github – Published: 2026-05-05 21:34 – Updated: 2026-05-13 13:52
VLAI
Summary
Grav has Unauthenticated Path Traversal & Arbitrary File Write in its FormFlash component
Details

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:

$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

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:
$ 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:
$ 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 — 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:

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "getgrav/grav"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.0.0-beta.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-42608"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-05T21:34:58Z",
    "nvd_published_at": "2026-05-11T16:17:33Z",
    "severity": "HIGH"
  },
  "details": "# Vulnerability Report: Grav CMS Unauthenticated Path Traversal \u0026 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[\u0027folder\u0027] ?? ($this-\u003esessionId ? \u0027tmp://forms/\u0027 . $this-\u003esessionId : \u0027\u0027);\n$this-\u003efolder = $folder \u0026\u0026 $locator-\u003eisStream($folder) ? $locator-\u003efindResource($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\u0027s scope (typically `user/config/`, `cache/`, `logs/`, and `tmp/`).\n\n## Affected Versions \u0026 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\u0026__form-flash-id=../../user/config/proof_dir\u0026form-data[name]=Attack\u0026form-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 \u0027/var/www/html/user/config/proof_dir/\u0027: 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: \u0027\u0027\nid: \u0027\u0027\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 \u2014 fix applied (2026-04-24)\n\nFixed in Grav core on the `2.0` branch: commit [`d904efc33`](https://github.com/getgrav/grav/commit/d904efc33) \u2014 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 `\u0027\u0027`, which causes `save()`/`delete()`/`getTmpDir()` to no-op \u2014 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) \u2014 32 test cases covering the PoC + variants.",
  "id": "GHSA-hmcx-ch82-3fv2",
  "modified": "2026-05-13T13:52:35Z",
  "published": "2026-05-05T21:34:58Z",
  "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"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "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",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Grav has Unauthenticated Path Traversal \u0026 Arbitrary File Write in its FormFlash component"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…
Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.


Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…