# Shopper: privilege escalation via improper Livewire admin component authorization

Three Livewire admin components in Shopper gated write actions on read-only view_users, letting a viewer self-grant permissions, create an admin user, or delete roles.

- Payout: Research
- Severity: high
- Program: Shopper
- Found by: therawdev
- Disclosed: 2026-09-11
- CVE: CVE-2026-56828
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-j328-xmgp-j4q3
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-j328-xmgp-j4q3
- Tags: area:web domain:web impact:ato impact:privesc kind:research platform:ghsa sev:high tech:php technique:incomplete-fix technique:source-review vuln:access-control vuln:account-takeover vuln:auth-bypass vuln:privilege-escalation

**Target:** Laravel Livewire admin components (Permissions, CreateTeamMember, RolePermission)
**Root cause:** State-mutating Livewire actions (togglePermission, removePermission, CreateTeamMember::store, RolePermission::deleteAction) authorize only the read-only view_users permission instead of access_setting, a residual gap from an incomplete prior fix (PR #511).
**Steps:**
1. Log in as a staff user holding only `view_users` + `access_dashboard`.
2. Mount the Permissions component; blade emits each permission `id` in `wire:click`, so IDs are enumerated.
3. Call `togglePermission($id)` to grant `access_setting` (or `delete_customers`, `edit_orders`, etc.) to own role.
4. Alternatively open CreateTeamMember slide-over and call `store()` with chosen password and `role_id` of the `admin` role (only `config('shopper.admin.roles.user')` is excluded).
5. Log out and log in as the newly created admin account.
6. Or call `RolePermission::deleteAction` on any role with `can_be_removed=true` to delete it.
**How found:** Reviewing the prior advisory GHSA-f946-9qp6-vgch and its fix commit fcd0c59, the researcher checked which write actions still used view_users and found three missed — including a brand-new file added by the security commit itself. The project's own regression tests (view_users-only actor toggling permissions and creating a manager) confirmed the gap.
**Exploitation:** A low-privileged viewer uses the exposed Livewire actions to grant themselves access_setting, unlocking all actions hardened in PR #511, or creates a fresh admin user with a known password and logs in as it — full admin takeover. Also enables RBAC DoS by deleting permissions/roles.
**Escalation:** Self-granting access_setting unlocks every action previously hardened by PR #511; creating an admin-role user yields full admin login.
**Insight:** After a mass authorization-fix commit, diff every authorize() call in the touched files and grep for the old permission string; also audit files newly added by the fix commit, since they inherit the pre-fix gate. Existing tests that pass with only the read permission are themselves proof of the bug.

