CVE-2026-56826
—Shopping privilege escalation through missing authorization in Settings components ## Summary Four Livewire components in the Settings area expose destructive Filament actions (`delete` / `edit`) that perform **no server-side authorization**. Any authenticated user who can reach the Settings pages — i.e. holding only the coarse `access_setting` permission, **without** being an admin and **without** any `delete_*`/`edit_*` permission — can delete tax zones, tax rates, shipping zones, and carrier (shipping-rate) options by invoking the component action directly over the Livewire endpoint. These records sit on the storefront checkout path, so deleting them breaks shipping-rate calculation, removes region-scoped payment methods, and corrupts tax resolution at checkout. This is inconsistent with the rest of the admin, where destructive actions are gated by granular permissions (e.g. `Settings/Locations/Index` uses `->authorize('delete_inventories')`, and `Order/Detail` gates mutating actions with `edit_orders`). ## Affected components | Component | File | Unauthorized action | |---|---|---| | `Settings\Zones\ZoneShippingOptions` | `packages/admin/src/Livewire/Components/Settings/Zones/ZoneShippingOptions.php:47` | `delete` → `CarrierOption::query()->find($arguments['id'])->delete()` (id is client-supplied) | | `Settings\Zones\Detail` | `packages/admin/src/Livewire/Components/Settings/Zones/Detail.php:46` | `delete` → `DeleteAction` on the bound `Zone` | | `Settings\Taxes\Detail` | `packages/admin/src/Livewire/Components/Settings/Taxes/Detail.php:42` | `delete` → `DeleteAction` on the bound `TaxZone` | | `Settings\Taxes\TaxRates` | `packages/admin/src/Livewire/Components/Settings/Taxes/TaxRates.php:97` | `delete` → `DeleteAction` on a `TaxRate` | Each file contains **zero** `authorize` calls, and the actions declare neither `->authorize()` nor an enforced `->visible()` guard. ## Details The Settings pages mount these as child Livewire components. The parent page authorizes `access_setting` (e.g. `Pages/Settings/Taxes.php:29`), but the child components do not re-check authorization, and their destructive actions carry no `->authorize()`. Because each Livewire component handles its own `/livewire/update` requests, the action executes purely on the page-level `access_setting` gate — there is no per-resource permission, and `delete_zones` / `delete_taxes` permissions are never even generated by the seeder (`packages/admin/database/seeders/PermissionsTableSeeder.php`). `ZoneShippingOptions::deleteAction()` is the clearest case — it deletes by an id taken straight from the client action arguments with no scoping and no permission check: ```php // packages/admin/src/Livewire/Components/Settings/Zones/ZoneShippingOptions.php public function deleteAction(): Action { return Action::make('delete') ->requiresConfirmation() // ... no ->authorize(), no ->visible() ->action(function (array $arguments): void { CarrierOption::query()->find($arguments['id'])->delete(); // client-controlled id // ... }); } ``` ## Proof of Concept Confirmed with the project's own test harness (Pest + Orchestra Testbench, SQLite) — the real Livewire/Filament code path, executed as a non-admin user holding only `access_setting`. ```php use Livewire\Livewire; use Shopper\Core\Models\{CarrierOption, Zone}; use Shopper\Livewire\Components\Settings\Zones\ZoneShippingOptions; use Tests\Core\Stubs\User; uses(Tests\Admin\TestCase::class); it('low-priv access_setting user deletes a CarrierOption with no authorization', function (): void { $attacker = User::factory()->create(); $attacker->givePermissionTo('access_setting'); // NOT admin, NO delete_* permission $this->actingAs($attacker, config('shopper.auth.guard')); $zone = Zone::factory()->create(); $option = CarrierOption::factory()->create(['zone_id' => $zone->id]); Livewire::test(ZoneShippingOptions::class, ['se
- Ecosystems
- composer
- Weakness
- CWE-862
- Vector
- CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:L
- GHSA
- GHSA-f7h9-qv4x-9x57 (medium)
In the news0 stories
No ingested article mentions this CVE yet.