CVE-2026-42613
Description
Grav is a file-based Web platform. Prior to 2.0.0-beta.2, 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 vulnerability is fixed in 2.0.0-beta.2.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
getgrav/gravPackagist | < 2.0.0-beta.2 | 2.0.0-beta.2 |
Affected products
1Patches
13d419a0dabd7Security: registration privilege strip + Grav 2.0 nonce-key bridge
3 files changed · +40 −4
CHANGELOG.md+8 −0 modified@@ -1,3 +1,11 @@ +# v3.8.2 +## 04/23/2026 + +1. [](#bugfix) + * [security] Fixed unauthenticated privilege escalation in `Login::register` (GHSA-pxm6-mhxr-q4mj): if an admin added `groups` or `access` to `user_registration.fields`, an attacker could self-register as super-admin by POSTing those values. Registration form input for those fields is now ignored with a log warning; server-side config, `default_values`, and invitations remain authoritative. +2. [](#improved) + * IP pseudonymization (rate-limit keys, remember-me cookie salt) now uses `Security::getNonceKey()` when running on Grav 2.0+, and continues to read `security.salt` from config on Grav 1.7. Tracks Grav 2.0's GHSA-3f29-pqwf-v4j4 remediation (HMAC key is no longer reachable via sandboxed Twig). + # v3.8.1 ## 04/17/2026
classes/Login.php+14 −4 modified@@ -19,6 +19,7 @@ use Grav\Common\Page\Interfaces\PageInterface; use Grav\Common\Page\Page; use Grav\Common\Page\Pages; +use Grav\Common\Security; use Grav\Common\Session; use Grav\Common\User\Interfaces\UserCollectionInterface; use Grav\Common\User\Interfaces\UserInterface; @@ -349,8 +350,13 @@ public function getIpKey(?string $ip = null): string $isIPv4 = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); $ipKey = $isIPv4 ? $ip : Utils::getSubnet($ip, $this->grav['config']->get('plugins.login.ipv6_subnet_size')); - // Pseudonymization of the IP - return sha1($ipKey . $this->grav['config']->get('security.salt')); + // Pseudonymization of the IP. Grav 2.0 moved the HMAC key out of Config + // (GHSA-3f29-pqwf-v4j4); fall back to the legacy key on Grav 1.7. + $key = method_exists(Security::class, 'getNonceKey') + ? Security::getNonceKey() + : (string) $this->grav['config']->get('security.salt'); + + return sha1($ipKey . $key); } /** @@ -581,9 +587,13 @@ public function rememberMe($var = null) $this->rememberMe->setExpireTime($timeout); // Hardening cookies with user-agent and random salt or - // fallback to use system based cache key + // fallback to use system based cache key. Grav 2.0 moved the HMAC key + // out of Config (GHSA-3f29-pqwf-v4j4); use it when available. $server_agent = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown'; - $data = $server_agent . $config->get('security.salt', $this->grav['cache']->getKey()); + $saltKey = method_exists(Security::class, 'getNonceKey') + ? Security::getNonceKey() + : (string) $config->get('security.salt', $this->grav['cache']->getKey()); + $data = $server_agent . $saltKey; $this->rememberMe->setSalt(hash('sha512', $data)); // Set cookie with correct base path of Grav install
login.php+18 −0 modified@@ -1023,6 +1023,13 @@ private function processUserRegistration(FormInterface $form, Event $event): voi $fields = (array)$this->config->get('plugins.login.user_registration.fields', []); + // Privilege fields must never be sourced from public registration form input — + // honoring attacker-supplied values would grant instant super-admin even if an + // administrator mistakenly added them to `user_registration.fields` + // (GHSA-pxm6-mhxr-q4mj). Server-side `default_values`, invitations, and the + // `plugins.login.user_registration.{groups,access}` config remain authoritative. + $privilegeFields = ['groups', 'access']; + foreach ($fields as $field) { // Process value of field if set in the page process.register_user $default_values = (array)$this->config->get('plugins.login.user_registration.default_values'); @@ -1040,6 +1047,17 @@ private function processUserRegistration(FormInterface $form, Event $event): voi } } + if (in_array($field, $privilegeFields, true)) { + if ($form_data->get($field) !== null) { + $this->grav['log']->warning(sprintf( + 'Login registration: ignored client-supplied "%s" from form submission (username=%s)', + $field, + is_string($username) ? $username : '<invalid>' + )); + } + continue; + } + if (!isset($data[$field]) && $form_data->get($field)) { $data[$field] = $form_data->get($field); }
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-pxm6-mhxr-q4mjghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-42613ghsaADVISORY
- github.com/getgrav/grav-plugin-login/commit/3d419a0dabd70aed1fd49afcd5919004a4141da1nvdWEB
- github.com/getgrav/grav/security/advisories/GHSA-pxm6-mhxr-q4mjnvdWEB
- github.com/getgrav/grav/security/advisories/GHSA-w48r-jppp-rcfwnvdWEB
News mentions
0No linked articles in our index yet.