Monitor vulnerabilities like this one. Sign up free to get alerted when software you use is affected.
8.1

Sylius API Allows Unauthorized Cart Item Addition

CVE-2026-31821 GHSA-wjmg-4cq5-m8hg GHSA-wjmg-4cq5-m8hg
Summary

Unauthenticated attackers can add items to other customers' carts if they know the cart token value. This can reveal sensitive information like email addresses, cart contents, and payment and shipment IDs. Affected versions of Sylius are fixed in 2.0.16, 2.1.12, and 2.2.3, so update to one of these versions or add an ownership check in the AddItemToCartHandler to fix the issue.

What to do
  • Update sylius sylius to version 2.0.16.
  • Update sylius sylius to version 2.1.12.
  • Update sylius sylius to version 2.2.3.
  • Update sylius sylius/sylius to version 2.0.16.
  • Update sylius sylius/sylius to version 2.1.12.
  • Update sylius sylius/sylius to version 2.2.3.
Affected software
VendorProductAffected versionsFix available
sylius sylius > 2.0.0 , <= 2.0.15 2.0.16
sylius sylius > 2.1.0 , <= 2.1.11 2.1.12
sylius sylius > 2.2.0 , <= 2.2.2 2.2.3
sylius sylius > 2.0.0 , <= 2.0.16
sylius sylius > 2.1.0 , <= 2.1.12
sylius sylius > 2.2.0 , <= 2.2.3
sylius sylius/sylius > 2.0.0 , <= 2.0.16 2.0.16
sylius sylius/sylius > 2.1.0 , <= 2.1.12 2.1.12
sylius sylius/sylius > 2.2.0 , <= 2.2.3 2.2.3
Original title
Sylius is Missing Authorization in API v2 Add Item Endpoint
Original description
### Impact
The `POST /api/v2/shop/orders/{tokenValue}/items` endpoint does not verify cart ownership. An unauthenticated attacker can add items to other registered customers' carts by knowing the cart `tokenValue`.

```
POST /api/v2/shop/orders/{tokenValue}/items
```

Other mutation endpoints (PUT, PATCH, DELETE) are **not affected**. API Platform loads the Order entity through the state provider for these operations, which triggers `VisitorBasedExtension` and returns 404 for unauthorized users.

An attacker who obtains a cart `tokenValue` can add arbitrary items to another customer's cart. The endpoint returns the full cart representation in the response (HTTP 201), potentially leaking:

- Customer email address
- Cart contents (products, quantities, prices)
- Address data (billing and shipping if set)
- Payment and shipment IDs
- Order totals and tax breakdown
- Checkout state

### Patches
The issue is fixed in versions: 2.0.16, 2.1.12, 2.2.3, and above.

### Workarounds
Add an ownership check in `AddItemToCartHandler` by injecting `UserContextInterface` and verifying the current user matches the cart owner before adding items.

#### Step 1. Patch the handler

Create new `src/CommandHandler/Cart/AddItemToCartHandler.php`:

```php
<?php

declare(strict_types=1);

namespace App\CommandHandler\Cart;

use Sylius\Bundle\ApiBundle\Command\Cart\AddItemToCart;
use Sylius\Bundle\ApiBundle\Context\UserContextInterface;
use Sylius\Component\Core\Factory\CartItemFactoryInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\OrderItemInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Core\Model\ShopUserInterface;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\Component\Core\Repository\ProductVariantRepositoryInterface;
use Sylius\Component\Order\Modifier\OrderItemQuantityModifierInterface;
use Sylius\Component\Order\Modifier\OrderModifierInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;

#[AsMessageHandler]
final readonly class AddItemToCartHandler
{
public function __construct(
private OrderRepositoryInterface $orderRepository,
private ProductVariantRepositoryInterface $productVariantRepository,
private OrderModifierInterface $orderModifier,
private CartItemFactoryInterface $cartItemFactory,
private OrderItemQuantityModifierInterface $orderItemQuantityModifier,
private UserContextInterface $userContext,
) {
}

public function __invoke(AddItemToCart $addItemToCart): OrderInterface
{
/** @var ProductVariantInterface|null $productVariant */
$productVariant = $this->productVariantRepository->findOneBy(['code' => $addItemToCart->productVariantCode]);

if ($productVariant === null) {
throw new \InvalidArgumentException('Product variant with given code has not been found.');
}

/** @var OrderInterface|null $cart */
$cart = $this->orderRepository->findCartByTokenValue($addItemToCart->orderTokenValue);

if ($cart === null) {
throw new \InvalidArgumentException('Cart with given token has not been found.');
}

$this->assertCartAccessible($cart);

/** @var OrderItemInterface $cartItem */
$cartItem = $this->cartItemFactory->createNew();
$cartItem->setVariant($productVariant);

$this->orderItemQuantityModifier->modify($cartItem, $addItemToCart->quantity);
$this->orderModifier->addToOrder($cart, $cartItem);

return $cart;
}

private function assertCartAccessible(OrderInterface $cart): void
{
if ($cart->isCreatedByGuest()) {
return;
}

$cartCustomer = $cart->getCustomer();

if (null === $cartCustomer || null === $cartCustomer->getUser()) {
return;
}

$currentUser = $this->userContext->getUser();

if (
$currentUser instanceof ShopUserInterface
&& $currentUser->getCustomer()?->getId() === $cartCustomer->getId()
) {
return;
}

throw new NotFoundHttpException('Cart not found.');
}
}
```

#### Step 2. Override the service

```diff
# config/services.yaml

services:
App\:
resource: '../src/*'
- exclude: '../src/{Entity,Kernel.php}'
+ exclude: '../src/{Entity,Kernel.php,CommandHandler}'

sylius_api.command_handler.cart.add_item_to_cart:
class: App\CommandHandler\Cart\AddItemToCartHandler
arguments:
$orderRepository: '@sylius.repository.order'
$productVariantRepository: '@sylius.repository.product_variant'
$orderModifier: '@sylius.modifier.order'
$cartItemFactory: '@sylius.factory.order_item'
$orderItemQuantityModifier: '@sylius.modifier.order_item_quantity'
$userContext: '@Sylius\Bundle\ApiBundle\Context\UserContextInterface'
tags:
- { name: messenger.message_handler, bus: sylius.command_bus }
```

#### Step 3. Clear cache

```bash
bin/console cache:clear
```

### Reporters

We would like to extend our gratitude to the following individuals for their detailed reporting and responsible disclosure of this vulnerability:
- @rokorolov

### For more information
If you have any questions or comments about this advisory:

- Open an issue in [Sylius issues](https://github.com/Sylius/Sylius/issues?q=sort%3Aupdated-desc+is%3Aissue+is%3Aopen)
- Email us at [[email protected]](mailto:[email protected])
nvd CVSS4.0 6.9
Vulnerability type
CWE-862 Missing Authorization
Published: 11 Mar 2026 · Updated: 13 Mar 2026 · First seen: 10 Mar 2026