GitHub Security Advisory: GHSA-wjmg-4cq5-m8hg
Package: sylius/sylius (COMPOSER)
Severity: MODERATE (CVSS 0.0)
CWE: CWE-862: Missing Authorization
Vulnerable versions: >= 2.2.0, <= 2.2.2
Patched in: 2.2.3

Summary: Sylius is Missing Authorization in API v2 Add Item Endpoint

Details:
### 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.');