PT-2026-90544 · Packagist · Shopper/Framework

CVE-2026-56828

·

Published

2026-09-11

·

Updated

2026-09-11

CVSS v3.1

8.8

High

VectorAV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

Summary

Three Livewire admin components in shopper/framework (latest master at commit fcd0c59, released as v2.8.0) gate state-mutating actions on the read-only view users permission. This is the same class as the issue Shopper fixed in v2.8.0 / PR #511 / GHSA-f946-9qp6-vgch — the PR moved most write actions from view users to access setting, but three were missed (one of them is a brand-new file added by the security commit itself).
A staff user holding only view users + access dashboard (a realistic "support" or "viewer" role per Shopper's own PermissionsTableSeeder) can: (1) self-escalate by granting any permission to their own role; (2) create a brand-new admin team member with a chosen password and the admin role and then log in as that user; (3) delete arbitrary permissions rows (RBAC DoS) or — when can be removed=true — delete entire roles.
CVSS 3.1: AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H = 8.8 (High). CWE-285 (Improper Authorization) + CWE-862 (Missing Authorization).

Vulnerable components (paths relative to repo root)

1) packages/admin/src/Livewire/Components/Settings/Team/Permissions.php

  • togglePermission(int $id) at line 28 calls $this->authorize('view users');
  • removePermission(int $id) at line 55 calls $this->authorize('view users');
The Permissions blade at packages/admin/resources/views/livewire/components/settings/team/permissions.blade.php line 34 emits every permission's id directly in wire:click handlers, so the attacker does not even need to guess IDs — the page itself enumerates them.
Net effect: any user who can mount the Permissions component (gated on view users) can grant any permission row to the bound $role. Granting access setting to the attacker's own role unlocks every action that PR #511 supposedly hardened with ->authorize('access setting'). Granting delete customers, edit orders, edit products, add brands, etc. is direct data-modification escalation.

2) packages/admin/src/Livewire/SlideOvers/CreateTeamMember.php

  • mount() at line 53 calls $this->authorize('view users');
  • store() at line 122 calls $this->authorize('view users');
This file is new file mode 100755 in commit fcd0c59 — it was created as part of the security fix and inherited the same misclassified gate.
store() creates a User with email verified at = now(), the attacker's chosen password, and any selected role id. The Radio::make('role id') options filter only excludes config('shopper.admin.roles.user'), so the admin role is selectable. Log out, log in as the new account → full admin.

3) packages/admin/src/Livewire/Pages/Settings/Team/RolePermission.php

  • deleteAction at lines 81-90: only gated by ->visible($this->role->can be removed), with no ->authorize() chain.
Page-level mount (line 52) requires only view users. For any role with can be removed = true, a view users-only user can call the action and delete the role (cascading the loss of permissions for every assigned user).

Self-confirmation in the project's own test suite

The following tests are green on master @ fcd0c59 — they ARE the PoC:
tests/Admin/Livewire/Components/Settings/Team/PermissionsTest.php
 line 14-16: `givePermissionTo('view users')` only
 line 36-45: "can toggle permission to role" — passes
 line 74-85: "can remove permission" — passes

tests/Admin/Livewire/SlideOvers/CreateTeamMemberTest.php
 line 16-18: `givePermissionTo('view users')` only
 line 29-56: "can create new team member" — passes, asserts the new user `hasRole('manager')`
A view users-only Livewire user actor successfully toggles permissions, removes permissions, and creates a new privileged user — verified by Shopper's own regression tests.

Suggested fix

Change $this->authorize('view users') to $this->authorize('access setting') in:
  • Permissions::togglePermission
  • Permissions::removePermission
  • Permissions::mount (defence in depth, matches TeamIndex)
  • CreateTeamMember::mount
  • CreateTeamMember::store
Add ->authorize('access setting') to RolePermission::deleteAction (matches the pattern already applied to generatePermissionsAction, createPermissionAction, and TeamIndex::DeleteAction).
Update the two regression tests to use access setting instead of view users so they accurately reflect the privilege boundary.

Resources

Credits

Reported by Vishal Shukla(@shukla304) using sechub.dev AI Agent

Support

If this disclosure was useful and if users would like to support continued open-source security research and responsible-disclosure work, they can sponsor at https://github.com/sponsors/therawdev — Shoppers thanks those who keeping open source safe.

Fix

Improper Authorization

Missing Authorization

Found an issue in the description? Have something to add? Feel free to write us 👾

Weakness Enumeration

Related Identifiers

CVE-2026-56828
GHSA-J328-XMGP-J4Q3

Affected Products

Shopper/Framework