CVE-2026-75837: Grav Group Blueprint Missing Authorization Allows Privilege Escalation to Super-Admin
A delegated Grav admin who can manage users but is not a super-admin can edit a user group to grant themselves full super-admin rights, because the group permission form never checks whether the…
The problem
The core Flex group blueprint (system/blueprints/user/group.yaml, lines 48-55) defines an access field but omits the security@: admin.super guard that the sibling account.yaml blueprint carries on its equivalent fields.
Any authenticated operator holding admin.users.update (but not admin.super) can POST to the group-edit endpoint and include access[admin][super]=true in the body. Because no field-level guard exists, Blueprint::dynamicSecurity() never marks the field as ignored, so BlueprintSchema::filterArray() retains it and FlexObject::save() writes it to user/config/groups.yaml.
Every member of that group is now a super-admin on the next request, opening the scheduler (cron to RCE) and Twig evaluation.
Proof of concept
A working proof-of-concept for CVE-2026-75837 in getgrav/grav, with the exact payload below.
POST /admin/accounts/groups/ops HTTP/1.1
Host: target.example.com
Cookie: grav-site-[hash]=<session>
Content-Type: application/x-www-form-urlencoded
data[access][admin][super]=1The guard mechanism works like this: when a blueprint field carries security@: admin.super, Blueprint::dynamicSecurity() (Blueprint.php:644-662) sets validate.ignore=true for non-super callers, and BlueprintSchema::filterArray() then drops the field before FlexObject::save() is reached.
The account.yaml blueprint was patched (CVE-2026-42613) to add this guard on its access and groups fields, but the functionally identical access block in group.yaml never received it.
The field's check_authorize: false annotation provides zero PHP-level enforcement (grep confirms no PHP consumers), so security@ was the only real control. Its absence means the nested admin.super: true leaf passes through Validation::filterArray (type: array, value_type: bool) without obstruction.
The fix in 2.0.14 adds security@: admin.super to the access field in group.yaml, mirroring the guard already present in account.yaml, so non-super callers have the field stripped before it reaches storage.
The fix
Upgrade to getgrav/grav 2.0.14 (patch commit 5192316f5bf0f033636f43561829d7fc13a4ab64). The fix adds security@: admin.super to the access field in system/blueprints/user/group.yaml. As an interim control, remove admin.users.update from any account that should not hold super-admin, or restrict group-edit routes to super-admin only via your web server.
Reported by zx (Jace).
Related research
- high · 7.7CVE-2026-76839CVE-2026-76839: Grav CMS Twig Sandbox Credential Leak via offsetGet()
- high · 5.9CVE-2026-74907CVE-2026-74907: Grav CMS Unauthenticated Path Traversal via plugin-asset-map.php
- critical · 8.8CVE-2026-75827CVE-2026-75827: Grav CMS Arbitrary File Write via Blueprint error_log Injection
- high · 8.8CVE-2026-72819CVE-2026-72819: Grav CMS Remote Code Execution via ZIP Upload