GHSA-J328-XMGP-J4Q3
Vulnerability from github – Published: 2026-09-11 21:28 – Updated: 2026-09-11 21:28Summary
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
deleteActionat 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::togglePermissionPermissions::removePermissionPermissions::mount(defence in depth, matchesTeam\Index)CreateTeamMember::mountCreateTeamMember::store
Add ->authorize('access_setting') to RolePermission::deleteAction (matches the pattern already applied to generatePermissionsAction, createPermissionAction, and Team\Index::DeleteAction).
Update the two regression tests to use access_setting instead of view_users so they accurately reflect the privilege boundary.
Resources
- Prior advisory of the same class: https://github.com/shopperlabs/shopper/security/advisories/GHSA-f946-9qp6-vgch
- Fix commit that introduced these residual gaps: https://github.com/shopperlabs/shopper/commit/fcd0c5920588702df5b874f432b1042abd77a50b
- CWE-285 Improper Authorization
- CWE-862 Missing Authorization
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.
{
"affected": [
{
"package": {
"ecosystem": "Packagist",
"name": "shopper/framework"
},
"ranges": [
{
"events": [
{
"introduced": "2.8.0"
},
{
"fixed": "2.9.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-56828"
],
"database_specific": {
"cwe_ids": [
"CWE-285",
"CWE-862"
],
"github_reviewed": true,
"github_reviewed_at": "2026-09-11T21:28:54Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "## Summary\n\nThree 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](https://github.com/shopperlabs/shopper/security/advisories/GHSA-f946-9qp6-vgch) \u2014 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).\n\nA staff user holding only `view_users` + `access_dashboard` (a realistic \"support\" or \"viewer\" role per Shopper\u0027s 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 \u2014 when `can_be_removed=true` \u2014 delete entire roles.\n\nCVSS 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).\n\n## Vulnerable components (paths relative to repo root)\n\n### 1) `packages/admin/src/Livewire/Components/Settings/Team/Permissions.php`\n\n- `togglePermission(int $id)` at line 28 calls `$this-\u003eauthorize(\u0027view_users\u0027);`\n- `removePermission(int $id)` at line 55 calls `$this-\u003eauthorize(\u0027view_users\u0027);`\n\nThe Permissions blade at `packages/admin/resources/views/livewire/components/settings/team/permissions.blade.php` line 34 emits every permission\u0027s `id` directly in `wire:click` handlers, so the attacker does not even need to guess IDs \u2014 the page itself enumerates them.\n\nNet 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\u0027s own role unlocks every action that PR #511 supposedly hardened with `-\u003eauthorize(\u0027access_setting\u0027)`. Granting `delete_customers`, `edit_orders`, `edit_products`, `add_brands`, etc. is direct data-modification escalation.\n\n### 2) `packages/admin/src/Livewire/SlideOvers/CreateTeamMember.php`\n\n- `mount()` at line 53 calls `$this-\u003eauthorize(\u0027view_users\u0027);`\n- `store()` at line 122 calls `$this-\u003eauthorize(\u0027view_users\u0027);`\n\nThis file is `new file mode 100755` in commit `fcd0c59` \u2014 it was created as part of the security fix and inherited the same misclassified gate.\n\n`store()` creates a `User` with `email_verified_at = now()`, the attacker\u0027s chosen password, and any selected `role_id`. The `Radio::make(\u0027role_id\u0027)` options filter only excludes `config(\u0027shopper.admin.roles.user\u0027)`, so the `admin` role is selectable. Log out, log in as the new account \u2192 full admin.\n\n### 3) `packages/admin/src/Livewire/Pages/Settings/Team/RolePermission.php`\n\n- `deleteAction` at lines 81-90: only gated by `-\u003evisible($this-\u003erole-\u003ecan_be_removed)`, with no `-\u003eauthorize()` chain.\n\nPage-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).\n\n## Self-confirmation in the project\u0027s own test suite\n\nThe following tests are green on master @ `fcd0c59` \u2014 they ARE the PoC:\n\n```\ntests/Admin/Livewire/Components/Settings/Team/PermissionsTest.php\n line 14-16: `givePermissionTo(\u0027view_users\u0027)` only\n line 36-45: \"can toggle permission to role\" \u2014 passes\n line 74-85: \"can remove permission\" \u2014 passes\n\ntests/Admin/Livewire/SlideOvers/CreateTeamMemberTest.php\n line 16-18: `givePermissionTo(\u0027view_users\u0027)` only\n line 29-56: \"can create new team member\" \u2014 passes, asserts the new user `hasRole(\u0027manager\u0027)`\n```\n\nA `view_users`-only Livewire user actor successfully toggles permissions, removes permissions, and creates a new privileged user \u2014 verified by Shopper\u0027s own regression tests.\n\n## Suggested fix\n\nChange `$this-\u003eauthorize(\u0027view_users\u0027)` to `$this-\u003eauthorize(\u0027access_setting\u0027)` in:\n\n- `Permissions::togglePermission`\n- `Permissions::removePermission`\n- `Permissions::mount` (defence in depth, matches `Team\\Index`)\n- `CreateTeamMember::mount`\n- `CreateTeamMember::store`\n\nAdd `-\u003eauthorize(\u0027access_setting\u0027)` to `RolePermission::deleteAction` (matches the pattern already applied to `generatePermissionsAction`, `createPermissionAction`, and `Team\\Index::DeleteAction`).\n\nUpdate the two regression tests to use `access_setting` instead of `view_users` so they accurately reflect the privilege boundary.\n\n## Resources\n\n- Prior advisory of the same class: https://github.com/shopperlabs/shopper/security/advisories/GHSA-f946-9qp6-vgch\n- Fix commit that introduced these residual gaps: https://github.com/shopperlabs/shopper/commit/fcd0c5920588702df5b874f432b1042abd77a50b\n- CWE-285 Improper Authorization\n- CWE-862 Missing Authorization\n\n### Credits\n\nReported by Vishal Shukla(@shukla304) using sechub.dev AI Agent\n\n### Support\n\nIf 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 \u2014 Shoppers thanks those who keeping open source safe.",
"id": "GHSA-j328-xmgp-j4q3",
"modified": "2026-09-11T21:28:54Z",
"published": "2026-09-11T21:28:54Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/shopperlabs/shopper/security/advisories/GHSA-j328-xmgp-j4q3"
},
{
"type": "PACKAGE",
"url": "https://github.com/shopperlabs/shopper"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "Shopper: privilege escalation via improper Livewire admin component authorization"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.