Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-59190

CVE-2026-59190: Grav Admin Plugin Auth Bypass Vulnerability

CVE-2026-59190 is an authentication bypass flaw in Grav Admin Plugin that allows authenticated attackers to change any user's password, including super administrators. This article covers technical details, affected versions, and mitigation.

Published:

CVE-2026-59190 Overview

CVE-2026-59190 is an Insecure Direct Object Reference (IDOR) vulnerability in the Grav CMS admin plugin (grav-plugin-admin). The flaw exists in the saveUser() function within classes/plugin/AdminController.php. An authenticated attacker holding the admin.users permission can change the password of any user, including the super administrator. The saveUser routine authorizes the caller's user-management permission but fails to verify whether the caller is permitted to edit the target account. The issue affects versions 1.10.52 and earlier and is tracked under [CWE-639: Authorization Bypass Through User-Controlled Key].

Critical Impact

A low-privileged administrator with admin.users rights can silently reset the super administrator's password and take full control of the Grav instance.

Affected Products

  • Grav CMS grav-plugin-admin versions 1.10.52 and earlier
  • Grav installations exposing /admin/user/{username}?task=save
  • Multi-administrator Grav deployments delegating admin.users permission

Discovery Timeline

  • 2026-07-10 - CVE-2026-59190 published to NVD
  • 2026-07-10 - Last updated in NVD database
  • Fix planned - Expected in grav-plugin-admin version 1.10.53

Technical Details for CVE-2026-59190

Vulnerability Analysis

Grav's admin interface exposes user management endpoints under /admin/user/{username}. The saveUser() handler in AdminController.php processes POST submissions with a task=save parameter and applies the supplied data[] payload to the target user object.

Before the patch, saveUser() performed a single authorization check: it verified that the calling user held the admin.users capability. It did not enforce a per-record check comparing the caller's privilege level against the target account's privilege level. As a result, any operator granted admin.users could submit data[password] for the admin account and overwrite the credential. The password field is preserved through cleanUserPost(), so the reset succeeds without additional validation.

Root Cause

The root cause is missing object-level authorization on the user record being modified. Grav treats admin.users as a global capability rather than scoping it against target account attributes such as access.admin.super or access.api.super. This matches the [CWE-639] pattern where authorization decisions rely on function-level checks while ignoring the identity of the object under change.

Attack Vector

Exploitation requires an authenticated session with the admin.users permission. The attacker sends a direct POST request to /admin/user/{targetUsername}?task=save with a body containing data[password]=<new_password>. The server accepts the write, hashes the new password, and stores it. The attacker then authenticates as the super administrator and pivots to arbitrary file management, plugin installation, and code execution through Grav's admin console.

php
            }
        }

+        // Prevent privilege escalation (IDOR): an admin.users manager who is not a
+        // super admin must not edit a super-admin account — otherwise they could
+        // silently reset the super admin's password (the `password` field survives
+        // cleanUserPost()) and take over the instance. See GHSA-p97c-g455-q447.
+        if (!$this->admin->authorize('admin.super')
+            && (!empty($user->get('access.admin.super')) || !empty($user->get('access.api.super')))) {
+            $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK') . ' save.', 'error');
+
+            return false;
+        }
+
        /** @var Data\Blueprint $blueprint */
        $blueprint = $user->blueprints();
        $data = $blueprint->processForm($this->admin->cleanUserPost((array)$this->data));

Source: GitHub Commit 88f7ce8. The patch adds an explicit check that blocks non-super-admin callers from saving accounts flagged with access.admin.super or access.api.super.

Detection Methods for CVE-2026-59190

Indicators of Compromise

  • POST requests to /admin/user/{username}?task=save where {username} is a super-admin account, submitted by a session that does not belong to that user
  • Request bodies containing data[password] targeting privileged accounts
  • Unexpected successful logins for super-admin accounts shortly after a saveUser request from a lower-privileged administrator
  • Modification timestamps on user/accounts/{admin}.yaml that do not correlate with legitimate admin activity

Detection Strategies

  • Parse Grav access logs for POST /admin/user/*?task=save events and correlate the acting session's user ID with the target {username} path segment; flag mismatches involving super-admin targets
  • Compare pre- and post-request state of user/accounts/*.yaml files to detect password hash changes on privileged accounts
  • Alert on any admin.users operator editing an account whose YAML contains access.admin.super: true or access.api.super: true

Monitoring Recommendations

  • Enable web server access logging with request bodies redacted but path and query strings preserved for the /admin/ prefix
  • Ingest Grav application logs into a centralized log platform and build a query for saveUser calls affecting privileged usernames
  • Monitor filesystem changes to user/accounts/ using file integrity monitoring and generate alerts on writes not originating from expected administrator sessions

How to Mitigate CVE-2026-59190

Immediate Actions Required

  • Upgrade grav-plugin-admin to version 1.10.53 or later as soon as the release is available from the Grav project
  • Audit all accounts holding the admin.users permission and revoke it from users who do not require it
  • Rotate the super administrator password and any other privileged credentials after applying the patch
  • Review recent modifications to user/accounts/*.yaml and Grav admin activity logs for unauthorized password changes

Patch Information

The fix is committed in grav-plugin-admin commit 88f7ce8 and documented in GitHub Security Advisory GHSA-p97c-g455-q447. The change adds an authorization check in saveUser() that blocks non-super-admin callers from modifying accounts with access.admin.super or access.api.super set.

Workarounds

  • Restrict the admin.users permission exclusively to accounts that also hold admin.super until the patch is applied
  • Place the /admin/ interface behind an authenticated reverse proxy or IP allowlist to reduce exposure of the vulnerable endpoint
  • Apply the upstream diff manually to classes/plugin/AdminController.php if an official release is not yet available in your channel
bash
# Configuration example: enforce IP allowlist for Grav admin via Nginx
location /admin/ {
    allow 10.0.0.0/24;      # trusted admin network
    deny  all;
    try_files $uri $uri/ /index.php?$query_string;
}

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.