Grav Form Plugin has an Anonymous Page Content Overwrite via Form File Upload filename Override
Date: 2026-05
Affected: composer/getgrav/grav-plugin-form
Attack vector: other
Category: vulnerability-disclosure
Severity: High
CVE: CVE-2026-42845
CWE: CWE-20
CWE-73

### Summary (Tested on Form 9.0.3 released on April, 28th) The Form plugin's file upload handler at `user/plugins/form/classes/Form.php:583` accepts a POST-supplied `filename` parameter (`$filename = $post['filename'] ?? $upload['file']['name']`) that overrides the original uploaded filename. The override passes through `Utils::checkFilename()`, which blocks only a narrow extension list (`.php*`, `.htm*`, `.js`, `.exe`). Markdown (`.md`) is **not** blocked. A page's directory under `user/pages/` contains its `.md` content file (e.g. `default.md`, `form.md`). When a form's file upload field has `accept: ['*']` (or any policy that admits text files), an unauthenticated visitor can: 1. Upload **arbitrary content** with **`filename=form.md`** (or other page-content filenames), 2. Submit the form to trigger `Form::copyFiles()`, which **overwrites the page's own `.md` file**. ### Details **Vulnerable code path** `user/plugins/form/classes/Form.php:580-606` (in `uploadFiles()`): ```php $grav->fireEvent('onFormUploadSettings', new Event(['settings' => &$settings, 'post' => $post])); $upload = json_decode(json_encode($this->normalizeFiles($_FILES['data'], $settings->name)), true); $filename = $post['filename'] ?? $upload['file']['name']; // ← POST-controlled // ... if (!Utils::checkFilename($filename)) { // ← extension blocklist only return ['status' => 'error', 'message' => 'Bad filename']; } ``` `Utils::checkFilename()` (`system/src/


Mitigations:

Architectural layers (MAESTRO):