Headline
CVE-2022-24747: NEXT-20309 - Fix cache control · shopware/platform@d518631
Shopware is an open commerce platform based on the Symfony php Framework and the Vue javascript framework. Affected versions of shopware do no properly set sensitive HTTP headers to be non-cacheable. If there is an HTTP cache between the server and client then headers may be exposed via HTTP caches. This issue has been resolved in version 6.4.8.2. There are no known workarounds.
Expand Up @@ -7,6 +7,7 @@ use Shopware\Core\Checkout\Cart\LineItem\LineItem; use Shopware\Core\Checkout\Cart\SalesChannel\CartService; use Shopware\Core\Checkout\Customer\CustomerEntity; use Shopware\Core\Framework\Event\BeforeSendResponseEvent; use Shopware\Core\Framework\Test\TestCaseBase\IntegrationTestBehaviour; use Shopware\Core\PlatformRequest; use Shopware\Core\SalesChannelRequest; Expand Down Expand Up @@ -34,7 +35,8 @@ public function testNoHeadersAreSetIfCacheIsDisabled(): void $this->createMock(CartService::class), 100, false, $this->getContainer()->get(MaintenanceModeResolver::class) $this->getContainer()->get(MaintenanceModeResolver::class), false );
$customer = $this->createMock(CustomerEntity::class); Expand Down Expand Up @@ -71,7 +73,8 @@ public function testGenerateCashHashWithItemsInCart($customer, Cart $cart, bool $service, 100, true, $this->getContainer()->get(MaintenanceModeResolver::class) $this->getContainer()->get(MaintenanceModeResolver::class), false );
$salesChannelContext = $this->createMock(SalesChannelContext::class); Expand Down Expand Up @@ -119,7 +122,8 @@ public function testMaintenanceRequest(bool $active, array $whitelist, bool $sho $cartService, 100, true, $this->getContainer()->get(MaintenanceModeResolver::class) $this->getContainer()->get(MaintenanceModeResolver::class), false );
$customer = $this->createMock(CustomerEntity::class); Expand Down Expand Up @@ -182,4 +186,74 @@ public function maintenanceRequest() yield ‘Do not cache requests of whitelisted ip’ => [true, [self::IP], false]; yield ‘Cache requests if ip is not whitelisted’ => [true, [‘120.0.0.0’], true]; }
/** * @dataProvider headerCases */ public function testResponseHeaders(bool $reverseProxyEnabled, ?string $beforeHeader, string $afterHeader): void { $response = new Response();
if ($beforeHeader) { $response->headers->set('cache-control’, $beforeHeader); }
$subscriber = new CacheResponseSubscriber( $this->createMock(CartService::class), 100, true, $this->createMock(MaintenanceModeResolver::class), $reverseProxyEnabled );
$subscriber->updateCacheControlForBrowser(new BeforeSendResponseEvent(new Request(), $response));
static::assertSame($afterHeader, $response->headers->get(‘cache-control’)); }
public function headerCases(): iterable { yield ‘no cache proxy, default response’ => [ false, null, 'no-cache, private’, ];
yield 'no cache proxy, default response with no-store (/account)' => [ false, 'no-store, private’, 'no-store, private’, ];
// @see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#preventing_storing yield ‘no cache proxy, no-cache will be replaced with no-store’ => [ false, 'no-store, no-cache, private’, 'no-store, private’, ];
yield ‘no cache proxy, public content served as private for end client’ => [ false, 'public, s-maxage=64000’, 'no-cache, private’, ];
yield ‘cache proxy, cache-control is not touched’ => [ true, 'public’, 'public’, ];
yield ‘cache proxy, cache-control is not touched #2’ => [ true, 'public, s-maxage=64000’, 'public, s-maxage=64000’, ];
yield ‘cache proxy, cache-control is not touched #3’ => [ true, 'private, no-store’, 'no-store, private’, // Symfony sorts the cache-control ]; } }