CVE-2022-24746 (PHP, published 2022-03-09T23:15Z)
Description: value: Shopware is an open commerce platform based on the Symfony php Framework and the Vue javascript framework. In affected versions it is possible to inject code via the voucher code form. This issue has been patched in version 6.4.8.1. There are no known workarounds for this issue.
Severity: MEDIUM (CVSS v3 base score: 6.1)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/shopware/platform
Files changed:
changelog/_unreleased/2022-02-03-add-filtering-to-product-and-promotion-codes.md
src/Core/Checkout/Cart/LineItemFactoryHandler/PromotionLineItemFactory.php
src/Core/Checkout/DependencyInjection/promotion.xml
src/Core/Checkout/Promotion/Cart/PromotionCollector.php
src/Storefront/Controller/CartLineItemController.php
src/Storefront/DependencyInjection/controller.xml
src/Storefront/Test/Controller/CartLineItemControllerTest.php
Commit message: NEXT-19276 - Add filtering to promotion and product codes


Vulnerable code:
        $uniqueKey = 'promotion-' . $data['referencedId'];
        $item->setReferencedId($data['referencedId']);
    public function __construct(PromotionGatewayInterface $gateway, PromotionItemBuilder $itemBuilder)
                $this->addPromotionNotFoundError($code, $original);
    /**
     * @var CartService
     */
    private $cartService;
    /**
     * @var PromotionItemBuilder
     */
    private $promotionItemBuilder;
    /**
     * @var SalesChannelRepositoryInterface
     */
    private $productRepository;
    /**
     * @var ProductLineItemFactory
     */
    private $productLineItemFactory;
        ProductLineItemFactory $productLineItemFactory
        $number = $request->request->get('number');
            $this->addFlash(self::DANGER, $this->trans('error.productNotFound', ['%number%' => $number]));
    public function testAddProductByNumber(string $productId, string $productNumber): void
        $this->createProduct($productId, $productNumber);

        static::assertArrayHasKey('success', $this->getFlashBag()->all());
        static::assertNotNull($cartLineItem);

Fixed code:
---
title: Add filtering to product and promotion codes
issue: NEXT-19276
author: Max Stegmeyer
author_email: m.stegmeyer@shopware.com
---
# Storefront
* Changed `Shopware\Storefront\Controller\CartLineItemController` to sanitize from promotion codes and product number error messages
        $code = $data['referencedId'];

        $uniqueKey = 'promotion-' . $code;
        $item->setReferencedId($code);
            <argument type="service" id="Shopware\Core\Framework\Util\HtmlSanitizer"/>
use Shopware\Core\Framework\Util\HtmlSanitizer;
    private HtmlSanitizer $htmlSanitizer;

    public function __construct(PromotionGatewayInterface $gateway, PromotionItemBuilder $itemBuilder, HtmlSanitizer $htmlSanitizer)
        $this->htmlSanitizer = $htmlSanitizer;

                $this->addPromotionNotFoundError($this->htmlSanitizer->sanitize($code, null, true), $original);
use Shopware\Core\Framework\Util\HtmlSanitizer;
    private CartService $cartService;
    private PromotionItemBuilder $promotionItemBuilder;
    private SalesChannelRepositoryInterface $productRepository;
    private ProductLineItemFactory $productLineItemFactory;

    private HtmlSanitizer $htmlSanitizer;
        ProductLineItemFactory $productLineItemFactory,
        HtmlSanitizer $htmlSanitizer
        $this->htmlSanitizer = $htmlSanitizer;
        $number = (string) $request->request->get('number');
            $this->addFlash(self::DANGER, $this->trans(
                'error.productNotFound',
                ['%number%' => $this->htmlSanitizer->sanitize($number, null, true)]
            ));
            <argument type="service" id="Shopware\Core\Framework\Util\HtmlSanitizer"/>
    public function testAddProductByNumber(?string $productId, string $productNumber): void
        if ($productId) {
            $this->createProduct($productId, $productNumber);
        }
        $flashBag = $this->getFlashBag()->all();
        if ($productId) {
            static::assertArrayHasKey('success', $flashBag);
            static::assertNotNull($cartLineItem);
        } else {
            static::assertArrayHasKey('danger', $flashBag);
            static::assertSame($this->getContainer()->get('translator')->trans('error.productNotFound', ['%number%' => \strip_tags($productNumber)]), $flashBag['danger'][0]);
            static::assertNull($cartLineItem);
        }
            [null, 'nonExisting'],
            [null, 'with<br>HTML'],
        ];
    }

    public function promotions(): array
    {
        return [
            ['testCode'],
            ['with<br>HTML'],
    /**
     * @dataProvider promotions
     */
    public function testAddPromotion(string $code): void
    {
        $contextToken = Uuid::randomHex();

        $cartService = $this->getContainer()->get(CartService::class);
        $request = $this->createRequest(['code' => $code]);

        $salesChannelContext = $this->createSalesChannelContext($contextToken);
        $this->getContainer()->get(CartLineItemController::class)->addPromotion(
            $cartService->getCart($contextToken, $salesChannelContext),
            $request,
            $salesChannelContext
        );

        $flashBag = $this->getFlashBag()->all();
        static::assertArrayHasKey('danger', $flashBag);
        static::assertSame($this->getContainer()->get('translator')->trans('checkout.promotion-not-found', ['%code%' => \strip_tags($code)]), $flashBag['danger'][0]);
        static::assertSame(0, $cartService->getCart($contextToken, $salesChannelContext)->getLineItems()->count());
    }