Skip to main content

Grav CMS CVE-2026-42613

CRITICAL
Improper Input Validation (CWE-20)
2026-05-05 https://github.com/getgrav/grav GHSA-pxm6-mhxr-q4mj
9.4
CVSS 3.1 · Vendor: https://github.com/getgrav/grav
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Identify Grav instance with registration enabled
  2. Delivery
    Craft POST with injected groups/access privilege fields
  3. Exploit
    Submit registration form to /user_register endpoint
  4. Execution
    Server saves attacker-controlled YAML account file
  5. Persist
    Authenticate to /admin with new super-admin credentials
  6. Impact
    Execute arbitrary code via admin panel RCE vectors

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A05:2025 - Injection
ASVS 5.0
V2 - Validation and Business Logic Input validation, allowlisting
Exploitation Conditions

User registration must be enabled in the Login plugin configuration (user_registration.enabled: true). The administrator must have added groups and/or access to the user_registration.fields array in user/config/plugins/login.yaml - this is NOT a default setting but is permitted without warning by the Grav admin interface. Vulnerable configurations look like: fields: [username, password, email, fullname, groups]. Default Grav installations with registration disabled or using only the default field set (username, password, email, fullname) are not exploitable. The vulnerability affects both authenticated and unauthenticated registration endpoints, but primary attack vector is unauthenticated self-registration. No specific network topology, user interaction, or platform dependency limits exploitation beyond the configuration precondition.

Impact

CVSS 9.4 (Critical) with AV:N/AC:L/PR:N/UI:N indicates remote unauthenticated exploitation with low complexity against default configurations. However, exploitation requires a non-default precondition: administrators must enable user registration AND add groups or access to the user_registration.fields list in login.yaml - a configuration the admin UI permits without warnings but not enabled by default. This significantly reduces real-world attack surface compared to the raw CVSS score, as most production Grav instances either disable public registration or use the default field set (username, password, email, fullname). The impact when exploitable is maximal: instant super-admin access chains to remote code execution via documented admin panel RCE vectors (GHSA-4fg4-8cr8-326m) or malicious plugin uploads. No EPSS or KEV data provided, but the availability of detailed POC code in the public GitHub security advisory lowers the skill barrier for exploitation. The fix is a simple server-side privilege field blocklist, confirmed in commit 3d419a0 - sites running Grav 2.0.0-beta.2 or Login plugin >=3.8.2 are protected. Sites on Grav 1.x must manually upgrade the Login plugin. The precondition requirement prevents this from being a widespread mass-exploitation risk despite the critical CVSS rating.

Exploit ScenarioDerived

An attacker identifies a Grav CMS instance with public user registration enabled and discovers the site accepts groups or access fields via form probing or error message disclosure. The attacker crafts a registration POST request to /user_register including data[groups][]=admins, data[access][admin][login]=true, and data[access][admin][super]=true alongside valid username, password, and email. The Login::register() method's isset() check finds these fields in the POST data, skips applying config-level defaults, and directly assigns the attacker-supplied privilege arrays to the new User object before saving to user/accounts/attacker.yaml. The attacker logs into /admin with the newly created super-admin account and leverages known admin panel RCE vectors or uploads a malicious plugin to execute arbitrary code on the server.

Act Now Prioritize within 24-48h. Why: CRITICAL severity.
Patch available 0.1% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – May 05, 2026

Unauthenticated privilege escalation in Grav CMS Login plugin 3.8.0 allows remote attackers to self-register with admin.super privileges via missing server-side validation of groups and access fields. When administrators configure user registration with groups or access in allowed fields (a permitted UI action), attackers inject these fields into registration POST requests to bypass config-level defaults and gain full administrative access. Vendor-released patch: Login plugin 3.8.2 / Grav 2.0.0-beta.2 (commit 3d419a0). No public exploit identified at time of analysis, but the GitHub security advisory includes detailed proof-of-concept code demonstrating the attack.

RemediationAI

Upgrade to Grav CMS 2.0.0-beta.2 or later, which pins Login plugin >=3.8.2 via admin2 blueprints and includes the fix. For Grav 1.x installations, manually update the Login plugin to version 3.8.2 or later from https://github.com/getgrav/grav-plugin-login/releases. The patch (commit 3d419a0dabd70aed1fd49afcd5919004a4141da1) adds a privilege field blocklist to the registration form handler that ignores groups and access from client input even when administrators include them in user_registration.fields, logging warnings on injection attempts. Compensating control if immediate patching is not feasible: remove groups and access from the user_registration.fields array in user/config/plugins/login.yaml, ensuring only safe fields (username, password, email, fullname, language) are included - this eliminates the attack vector but prevents legitimate group assignment during registration; alternatively, disable public user registration entirely by setting user_registration.enabled: false until patching is complete. Note that disabling registration may impact user onboarding workflows, while restricting fields prevents admin-intended group selection features from functioning.

Affected Packages

composer getgrav/grav fix: 2.0.0-beta.2

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 1 package in composer

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

This vulnerability exists in the Login plugin for Grav CMS, a flat-file content management system written in PHP. The Login::register() method in classes/Login.php uses PHP's isset() to check for groups and access fields in POST data, applying config defaults only when these fields are absent. When present in attacker input, the fields bypass all validation - the validateField() method's switch statement only validates username, password, password2, email, permissions, state, and language, passing groups and access through the default case with no sanitization. The resulting User object is saved with attacker-controlled privilege arrays written directly to YAML account files under user/accounts/. This violates CWE-20 (Improper Input Validation) by trusting client-supplied authorization data without server-side enforcement of allowed values. The vulnerability represents a mass assignment issue where the framework's field allowlist is treated as a user preference rather than a security boundary.

Know when PHP gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

Vendor (https://github.com/getgrav/grav) PRIMARY 9.4 CRITICAL
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L

Primary rating from Vendor (https://github.com/getgrav/grav) · only source for this CVE.

CVSS VectorVendor: https://github.com/getgrav/grav

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

DescriptionCVE.org

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). On the Grav 2.0 line, the login plugin is pinned at >=3.8.2 by admin2's 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 - form handler privilege-field strip.

Executive ViewAI

Why It Matters

Grav CMS Login plugin versions prior to 3.8.2 contain a critical unauthenticated privilege escalation vulnerability that allows attackers to self-register with full administrative access by injecting admin fields during account creation. Organizations running affected Grav instances face immediate risk of complete system compromise and unauthorized administrative control without requiring valid credentials or authenticated access.

Business Impact: Severe
Compensating Controls

If immediate patching is not feasible: (1) Disable user self-registration functionality in Grav admin configuration to prevent exploit execution; (2) Implement network-level access controls restricting registration endpoints to trusted networks; (3) Enable audit logging for all account creation events and monitor for registrations with elevated privileges; (4) Conduct immediate forensic review of existing user accounts for suspicious administrative access creation.

Threat Intelligence Overview

EPSS Score
0.1%
Top 83% exploitable
Threat Intel
1
1 source
Data Quality
4 sources
Confidence: Medium

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity CRITICAL
CISA KEV No
Public POC No
EPSS 0.1%
Patch available Yes
Active threat No
Deciding rule
CRITICAL severity
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Out-of-Cycle
Exploitation· derived
None
System Exposure· derived
Open
Automatable· derived
Yes
Human Impact
Very High

Priority Score

47
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +47
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Privilege escalation occurs when an attacker leverages flaws in access control mechanisms to gain permissions beyond what they were originally granted.

Affected Products (CPE)CVE.org

pkg:composer/getgrav_grav

More in PHP

View all
CVE-2019-11043 CRITICAL POC
9.8 Oct 28

In PHP versions 7.1.x below 7.1.33, 7.2.x below 7.2.24 and 7.3.x below 7.3.11 in certain configurations of FPM setup it

CVE-2012-1823 CRITICAL POC
9.8 May 11

sapi/cgi/cgi_main.c in PHP before 5.3.12 and 5.4.x before 5.4.2, when configured as a CGI script (aka php-cgi), does not

CVE-2016-1555 CRITICAL POC
9.8 Apr 21

(1) boardData102.php, (2) boardData103.php, (3) boardDataJP.php, (4) boardDataNA.php, and (5) boardDataWW.php in Netgear

CVE-2018-11138 CRITICAL POC
9.8 May 31

The '/common/download_agent_installer.php' script in the Quest KACE System Management Appliance 8.0.318 is accessible by

CVE-2024-11680 CRITICAL POC
9.8 Nov 26

ProjectSend versions prior to r1720 are affected by an improper authentication vulnerability. Rated critical severity (C

CVE-2025-49113 CRITICAL POC
9.9 Jun 02

Roundcube Webmail contains a critical PHP object deserialization vulnerability (CVE-2025-49113, CVSS 9.9) that allows au

CVE-2017-9841 CRITICAL POC
9.8 Jun 27

Util/PHP/eval-stdin.php in PHPUnit before 4.8.28 and 5.x before 5.6.3 allows remote attackers to execute arbitrary PHP c

CVE-2025-0108 HIGH POC
8.8 Feb 12

Palo Alto Networks PAN-OS management web interface contains an authentication bypass allowing unauthenticated attackers

CVE-2021-25298 HIGH POC
8.8 Feb 15

Nagios XI version xi-5.7.5 is affected by OS command injection. Rated high severity (CVSS 8.8), this vulnerability is re

CVE-2021-25296 HIGH POC
8.8 Feb 15

Nagios XI version xi-5.7.5 is affected by OS command injection. Rated high severity (CVSS 8.8), this vulnerability is re

CVE-2013-4983 CRITICAL POC
10.0 Sep 10

The get_referers function in /opt/ws/bin/sblistpack in Sophos Web Appliance before 3.7.9.1 and 3.8 before 3.8.1.1 allows

CVE-2023-6553 CRITICAL POC
9.8 Dec 15

The Backup Migration plugin for WordPress is vulnerable to Remote Code Execution in all versions up to, and including, 1

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy