VYPR
Moderate severityNVD Advisory· Published Jan 17, 2023· Updated Mar 10, 2025

Improper Input Validation of Clearance sale in cart

CVE-2023-22730

Description

Shopware is an open source commerce platform based on Symfony Framework and Vue js. In affected versions It was possible to put the same line item multiple times in the cart using the AP. The Cart Validators checked the line item's individuality and the user was able to bypass quantity limits in sales. This problem has been fixed with version 6.4.18.1. Users on major versions 6.1, 6.2, and 6.3 may also obtain this fix via a plugin.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Shopware 6 allowed users to add duplicate line items via the API, bypassing quantity limits and clearance sale restrictions.

Vulnerability

Overview

CVE-2023-22730 is a logic flaw in Shopware 6's cart validation mechanism. The Cart Validators did not enforce uniqueness of line items, permitting a user to add the same product multiple times through the API without triggering any error [1]. The root cause was the absence of a dedicated validator to check for duplicate product line items and aggregate their quantities [2].

Exploitation

An attacker can exploit this vulnerability by sending crafted API requests to repeatedly add the same line item (product) to the shopping cart. No special privileges are required; the API endpoint is accessible to any authenticated or guest user. The cart validators evaluate each line item individually but fail to detect when the same product ID appears multiple times [1][4].

Impact

By bypassing the line-item individuality check, an attacker can exceed the intended quantity limits set by the merchant. This can be used to circumvent clearance sale restrictions (e.g., purchase more items than the sale allows) or to manipulate inventory counts, potentially causing financial loss or stock discrepancies [4].

Mitigation

The issue has been patched in Shopware version 6.4.18.1. For users on older major versions (6.1, 6.2, 6.3), a plugin is available to provide the same fix [1][4]. Administrators are strongly advised to update to the latest version or apply the plugin to prevent exploitation.

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
shopware/platformPackagist
< 6.4.18.16.4.18.1
shopware/corePackagist
< 6.4.18.16.4.18.1

Affected products

3

Patches

1
4fce12096e54

NEXT-23325 - Add product line item validator for duplicate line items with stock issues

https://github.com/shopware/platformMax StegmeyerDec 11, 2022via ghsa
5 files changed · +185 2
  • changelog/_unreleased/2022-12-12-fix-quantity-issues-on-duplicate-product-line-items.md+6 0 added
    @@ -0,0 +1,6 @@
    +---
    +title: Fix quantity issues on duplicate product line items
    +issue: NEXT-23325
    +---
    +# Core
    +* Added `Shopware\Core\Content\Product\Cart\ProductLineItemValidator` to check product quantity limits across product line items
    
  • src/Core/Checkout/DependencyInjection/cart.xml+4 0 modified
    @@ -203,6 +203,10 @@
                 <argument type="tagged" tag="shopware.cart.validator"/>
             </service>
     
    +        <service id="Shopware\Core\Content\Product\Cart\ProductLineItemValidator">
    +            <tag name="shopware.cart.validator"/>
    +        </service>
    +
             <service id="Shopware\Core\Checkout\Cart\Processor">
                 <argument type="service" id="Shopware\Core\Checkout\Cart\Validator"/>
                 <argument type="service" id="Shopware\Core\Checkout\Cart\Price\AmountCalculator"/>
    
  • src/Core/Content/Product/Cart/ProductLineItemValidator.php+64 0 added
    @@ -0,0 +1,64 @@
    +<?php declare(strict_types=1);
    +
    +namespace Shopware\Core\Content\Product\Cart;
    +
    +use Shopware\Core\Checkout\Cart\Cart;
    +use Shopware\Core\Checkout\Cart\CartValidatorInterface;
    +use Shopware\Core\Checkout\Cart\Error\ErrorCollection;
    +use Shopware\Core\Checkout\Cart\LineItem\LineItem;
    +use Shopware\Core\System\SalesChannel\SalesChannelContext;
    +
    +/**
    + * @package checkout
    + */
    +class ProductLineItemValidator implements CartValidatorInterface
    +{
    +    public function validate(Cart $cart, ErrorCollection $errors, SalesChannelContext $context): void
    +    {
    +        $productLineItems = array_filter($cart->getLineItems()->getFlat(), static function (LineItem $lineItem) {
    +            return $lineItem->getType() === LineItem::PRODUCT_LINE_ITEM_TYPE;
    +        });
    +
    +        foreach ($productLineItems as $lineItem) {
    +            $productId = $lineItem->getReferencedId();
    +            if ($productId === null) {
    +                continue;
    +            }
    +            $totalQuantity = $this->getTotalQuantity($productId, $productLineItems);
    +
    +            $quantityInformation = $lineItem->getQuantityInformation();
    +            if ($quantityInformation === null) {
    +                continue;
    +            }
    +
    +            $minPurchase = $quantityInformation->getMinPurchase();
    +            $available = $quantityInformation->getMaxPurchase() ?? 0;
    +            $steps = $quantityInformation->getPurchaseSteps() ?? 1;
    +
    +            if ($available >= $totalQuantity) {
    +                continue;
    +            }
    +
    +            $maxAvailable = (int) (floor(($available - $minPurchase) / $steps) * $steps + $minPurchase);
    +
    +            $cart->addErrors(
    +                new ProductStockReachedError($productId, (string) $lineItem->getLabel(), $maxAvailable, false),
    +            );
    +        }
    +    }
    +
    +    /**
    +     * @param LineItem[] $productLineItems
    +     */
    +    private function getTotalQuantity(string $productId, array $productLineItems): int
    +    {
    +        $totalQuantity = 0;
    +        foreach ($productLineItems as $lineItem) {
    +            if ($lineItem->getReferencedId() === $productId) {
    +                $totalQuantity += $lineItem->getQuantity();
    +            }
    +        }
    +
    +        return $totalQuantity;
    +    }
    +}
    
  • src/Core/Content/Product/Cart/ProductStockReachedError.php+10 2 modified
    @@ -22,7 +22,9 @@ class ProductStockReachedError extends Error
          */
         protected $quantity;
     
    -    public function __construct(string $id, string $name, int $quantity)
    +    protected bool $resolved;
    +
    +    public function __construct(string $id, string $name, int $quantity, bool $resolved = true)
         {
             $this->id = $id;
     
    @@ -35,6 +37,7 @@ public function __construct(string $id, string $name, int $quantity)
             parent::__construct($this->message);
             $this->name = $name;
             $this->quantity = $quantity;
    +        $this->resolved = $resolved;
         }
     
         public function getParameters(): array
    @@ -64,11 +67,16 @@ public function getMessageKey(): string
     
         public function getLevel(): int
         {
    -        return self::LEVEL_WARNING;
    +        return $this->resolved ? self::LEVEL_WARNING : self::LEVEL_ERROR;
         }
     
         public function blockOrder(): bool
         {
             return true;
         }
    +
    +    public function isPersistent(): bool
    +    {
    +        return $this->resolved;
    +    }
     }
    
  • tests/unit/php/Core/Content/Product/Cart/ProductLineItemValidatorTest.php+101 0 added
    @@ -0,0 +1,101 @@
    +<?php declare(strict_types=1);
    +
    +namespace Shopware\Tests\Unit\Core\Content\Product\Cart;
    +
    +use PHPUnit\Framework\TestCase;
    +use Shopware\Core\Checkout\Cart\Cart;
    +use Shopware\Core\Checkout\Cart\LineItem\QuantityInformation;
    +use Shopware\Core\Content\Product\Cart\ProductLineItemFactory;
    +use Shopware\Core\Content\Product\Cart\ProductLineItemValidator;
    +use Shopware\Core\Framework\Uuid\Uuid;
    +use Shopware\Core\System\SalesChannel\SalesChannelContext;
    +
    +/**
    + * @internal
    + * @covers \Shopware\Core\Content\Product\Cart\ProductLineItemValidator
    + */
    +class ProductLineItemValidatorTest extends TestCase
    +{
    +    public function testValidateOnDuplicateProductsAtMaxPurchase(): void
    +    {
    +        $cart = new Cart(Uuid::randomHex(), Uuid::randomHex());
    +        $builder = new ProductLineItemFactory();
    +        $cart->add(
    +            $builder
    +            ->create('product-1')
    +            ->setQuantityInformation(
    +                (new QuantityInformation())
    +                ->setMinPurchase(1)
    +                ->setMaxPurchase(1)
    +                ->setPurchaseSteps(1)
    +            )
    +        );
    +        $cart->add(
    +            $builder
    +            ->create('product-2')
    +            ->setReferencedId('product-1')
    +            ->setQuantityInformation(
    +                (new QuantityInformation())
    +                ->setMinPurchase(1)
    +                ->setMaxPurchase(1)
    +                ->setPurchaseSteps(1)
    +            )
    +        );
    +
    +        static::assertCount(0, $cart->getErrors());
    +
    +        $validator = new ProductLineItemValidator();
    +        $validator->validate($cart, $cart->getErrors(), $this->createMock(SalesChannelContext::class));
    +
    +        static::assertCount(1, $cart->getErrors());
    +    }
    +
    +    public function testValidateOnDuplicateProductsWithSafeQuantity(): void
    +    {
    +        $cart = new Cart(Uuid::randomHex(), Uuid::randomHex());
    +        $builder = new ProductLineItemFactory();
    +        $cart->add(
    +            $builder
    +            ->create('product-1')
    +            ->setQuantityInformation(
    +                (new QuantityInformation())
    +                ->setMinPurchase(1)
    +                ->setMaxPurchase(3)
    +                ->setPurchaseSteps(1)
    +            )
    +        );
    +        $cart->add(
    +            $builder
    +            ->create('product-2')
    +            ->setReferencedId('product-1')
    +            ->setQuantityInformation(
    +                (new QuantityInformation())
    +                ->setMinPurchase(1)
    +                ->setMaxPurchase(3)
    +                ->setPurchaseSteps(1)
    +            )
    +        );
    +
    +        static::assertCount(0, $cart->getErrors());
    +
    +        $validator = new ProductLineItemValidator();
    +        $validator->validate($cart, $cart->getErrors(), $this->createMock(SalesChannelContext::class));
    +
    +        static::assertCount(0, $cart->getErrors());
    +    }
    +
    +    public function testValidateOnDuplicateProductsWithoutQuantityInformation(): void
    +    {
    +        $cart = new Cart(Uuid::randomHex(), Uuid::randomHex());
    +        $builder = new ProductLineItemFactory();
    +        $cart->add($builder->create('product-1'));
    +        $cart->add($builder->create('product-2')->setReferencedId('product-1'));
    +
    +        static::assertCount(0, $cart->getErrors());
    +
    +        $validator = new ProductLineItemValidator();
    +        $validator->validate($cart, $cart->getErrors(), $this->createMock(SalesChannelContext::class));
    +
    +        static::assertCount(0, $cart->getErrors());
    +    }
    +}
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.