github shopperlabs/shopper v2.8.0

3 hours ago

Security Release

This release patches multiple authorization bypasses in the admin Livewire surface and a long-standing race condition on Discount.usage_limit reported against v2.7.3. Upgrading is strongly recommended for every Shopper install.

Two GitHub Security Advisories are published alongside this tag, disclosed responsibly by @baradika:

  • Authorization bypass in multiple Livewire admin components (CWE-862 / CWE-285)
  • Race condition on Discount.usage_limit allows silent over-redemption (CWE-362 / CWE-840)

Security Fixes

  • fix(security): require edit_orders on all Order/Detail and Order/Shipments Filament actions (cancel, startProcessing, markPaid, markComplete, capturePayment, archive, markDelivered, edit) by @mckenziearts in #511
  • fix(security): require edit_products inside Products/Form/{Edit,Inventory,Seo,Shipping,Files}::store() by @mckenziearts in #511
  • fix(security): require edit_orders on OrderNotes::leaveNotes() by @mckenziearts in #511
  • fix(security): require access_setting on Settings/Team/Index::createRole and DeleteAction by @mckenziearts in #511
  • fix(security): require access_setting on Settings/Team/RolePermission write actions by @mckenziearts in #511
  • fix(security): require access_setting on PaymentMethods, Currencies, Carriers ToggleColumn, record actions and bulk actions by @mckenziearts in #511
  • fix(security): require correct permission on Locations/InventoryForm::store() and Legal/PolicyForm::store() sub-components by @mckenziearts in #511
  • fix(security): lock public Eloquent properties with #[Locked] on every Livewire component exposing a model (Order, OrderShipping, Discount, Review, ShopperUser, Role, Inventory, Legal, Product) by @mckenziearts in #511
  • fix(security): switch product barcode TextInput to regex('/^[A-Za-z0-9\-]*$/') to close stored XSS on the admin barcode renderer by @mckenziearts in #511
  • fix(security): drop _password hidden-field leak in Customers/Create::store() (replace Arr::except with explicit Arr::only allow-list) by @mckenziearts in #511
  • fix(security): guard Settings/Team/Permissions::togglePermission and removePermission against null Permission lookups by @mckenziearts in #511

Bug Fixes

  • fix(cart): reserve the discount slot atomically before order creation in CreateOrderFromCartAction, fixing silent over-redemption when usage_limit was reached between cart validation and commit (issue #510) by @mckenziearts in #511
  • fix(cart): enforce usage_limit_per_user by counting prior orders on the new orders.discount_id column instead of the never-incremented DiscountDetail.total_use counter by @mckenziearts in #511
  • fix(cart): surface the per-user limit at cart-apply time via DiscountValidator so the rejection no longer surprises the customer at checkout by @mckenziearts in #511

Improvements

  • refactor(admin): migrate Filament Action handlers from $this->authorize() inside the closure to ->authorize('ability') chained on the action, so forbidden actions are hidden in the UI instead of throwing on click by @mckenziearts in #511

Upgrading

This release includes one additive migration. Run after pulling:

composer update shopper/admin shopper/cart shopper/core
php artisan migrate

The migration adds the following columns to the orders table:

  • discount_id — nullable foreign key referencing discounts.id (nullOnDelete)
  • discount_code, discount_type, discount_value_at_apply, discount_currency_code — snapshot fields preserved when the originating discount is later edited or deleted

All columns are nullable. Existing rows are left untouched.

If you have custom Livewire components extending Shopper's order/product/settings surfaces, review them for the same authorization pattern: every ->action(...) handler should either chain ->authorize('ability') on the Filament Action, or call $this->authorize('ability') on the first line of a Livewire method.

Credits

Authorization bypasses and the discount race condition were reported privately and responsibly by Fase Rais Baradika.

Full Changelog: v2.7.3...v2.8.0

Don't miss a new shopper release

NewReleases is sending notifications on new releases.