See how shopware compares to other vendors in security performance
Shopware is an open commerce platform. /api/info/config route exposes information about licenses. This vulnerability is fixed in 7.8.1 and 6.10.15.
Shopware is an open commerce platform. /api/info/config route exposes information about active security fixes. This vulnerability is fixed in 2.0.16, 3.0.12, and 4.0.7.
Summary
We identified and fixed a vulnerability in the Shopware app registration flow that could, under specific conditions, allow attackers to take over the communication channel between a shop and an app. By abusing app re‑registration, an attacker could redirect app traffic to an attacker‑controlled domain and potentially obtain API credentials intended for the legitimate shop. We have no evidence that this vulnerability has been exploited.
---
Affected Scope
- All apps (public and private) that use a registrationUrl in their app manifest and rely on the legacy HMAC‑based registration flow. - Both on‑premise and cloud installations are affected until updated to a fixed Shopware version or protected by the latest Shopware Security Plugin. - Shopware services and first‑party apps using the affected SDKs were reviewed and patched. The vulnerability does not affect core storefront or administration authentication; it is limited to the app system’s registration and re‑registration mechanism.
---
Impact
In a successful attack, an attacker who already knows certain app‑side secrets could: - Re‑register an existing app installation with a domain under their control. - Intercept App → Shop communication and cause data tampering (“data poisoning”). - Obtain API integration credentials of the shop with the permissions granted to the app. Shop owners and app manufacturers would typically observe this as “app malfunction” rather than an obvious security issue, which increases the need for hardening.
---
Root Cause
The legacy app registration flow used HMAC‑based authentication without sufficiently binding a shop installation to its original domain. During re‑registration, the shop-url could be updated without proving control over the previously registered shop or domain. This made targeted hijacking of app communication feasible if an attacker possessed the relevant app‑side secret.
---
Fix
We have hardened the app registration and re‑registration process: - Dual signature requirement: Re‑registration now requires both the app secret and the existing shop secret to be presented and validated. - Mandatory secret rotation: On successful re‑registration, a new shop secret is generated and verified; the previous secret is invalidated after a short grace period. - Stricter validation: Shopware only accepts updated shop URLs and secrets once the full confirmation flow has completed successfully. - Improved logging and monitoring: All re‑registrations are now logged with additional metadata to help detect abuse patterns. These changes are delivered via: - Updated Shopware core releases (6.6.x, 6.7.x), and - Updated versions of the Shopware Security Plugin for supported older versions, - Updated official SDKs (e.g. PHP and JavaScript app SDKs). ---
Required Action
For Merchants / Shop Operators
1. Update Shopware - Upgrade to the latest Shopware 6.6.x / 6.7.x release that includes this fix, or - Install/update the latest Shopware Security Plugin version providing the hotfix for your Shopware 6 installation. 2. Update apps - Ensure all installed apps are updated to the latest versions provided by their manufacturers. - If you suspect compromised keys or observe unexpected app behaviour, re‑install the affected app or trigger key rotation as documented by the app vendor.
For App Manufacturers / Partners
1. Update SDKs / implementations - Update to the latest Shopware app SDKs (PHP / JS) or apply the documented changes if you maintain a custom implementation of the registration flow. - Validate both shopware-app-signature and shopware-shop-signature for re‑registration requests. - Always generate and store a new shop secret on re‑registration and only switch to it after a successful confirmation. 2. Review your apps - Verify that your app does not blindly accept changed shop-url values without validating signatures. - Check any logic that exposes data or functionality based solely on HMAC signatures from shops and ensure it aligns with the hardened registration model. 3. Test your implementation - Use the updated tooling and guidance provided in your Shopware Account / partner channels to validate that your registration flow complies with the new requirements.
Summary
The Store API login endpoint (POST /store-api/account/login) returns different error codes depending on whether the submitted email address belongs to a registered customer (CHECKOUTCUSTOMERAUTHBADCREDENTIALS) or is unknown (CHECKOUTCUSTOMERNOTFOUND). The "not found" response also echoes the probed email address. This allows an unauthenticated attacker to enumerate valid customer accounts. The storefront login controller correctly unifies both error paths, but the Store API does not — indicating an inconsistent defense.
CWE
- CWE-204: Observable Response Discrepancy
Description
Distinct error codes leak account existence
The login flow in AccountService::getCustomerByLogin() calls getCustomerByEmail() first, which throws CustomerNotFoundException if the email is not found. If the email IS found but the password is wrong, a separate BadCredentialsException is thrown:
php // src/Core/Checkout/Customer/SalesChannel/AccountService.php:116-145 public function getCustomerByLogin(string $email, string $password, SalesChannelContext $context): CustomerEntity { if ($this->isPasswordTooLong($password)) { throw CustomerException::badCredentials(); }
$customer = $this->getCustomerByEmail($email, $context); // ↑ Throws CustomerNotFoundException with CHECKOUTCUSTOMERNOTFOUND if email unknown
if ($customer->hasLegacyPassword()) { if (!$this->legacyPasswordVerifier->verify($password, $customer)) { throw CustomerException::badCredentials(); // ↑ Throws BadCredentialsException with CHECKOUTCUSTOMERAUTHBADCREDENTIALS } // ... }
if ($customer->getPassword() === null || !passwordverify($password, $customer->getPassword())) { throw CustomerException::badCredentials(); // ↑ Same: CHECKOUTCUSTOMERAUTHBADCREDENTIALS } // ... }
The two exception types produce clearly distinguishable API responses:
Email not registered: json { "errors": [{ "status": "401", "code": "CHECKOUTCUSTOMERNOTFOUND", "detail": "No matching customer for the email \"probe@example.com\" was found.", "meta": { "parameters": { "email": "probe@example.com" } } }] }
Email registered, wrong password: json { "errors": [{ "status": "401", "code": "CHECKOUTCUSTOMERAUTHBADCREDENTIALS", "detail": "Invalid username and/or password." }] }
Storefront is protected — Store API is not
The storefront login controller demonstrates that Shopware's developers are aware of this risk class. AuthController::login() catches both exceptions together and returns a generic error:
php // src/Storefront/Controller/AuthController.php:203 } catch (BadCredentialsException|CustomerNotFoundException) { // Unified handling — no distinction exposed to the user }
The Store API LoginRoute::login() does NOT catch these exceptions. They propagate to the global ErrorResponseFactory, which serializes the distinct error codes into the JSON response:
php // src/Core/Checkout/Customer/SalesChannel/LoginRoute.php:54-58 $token = $this->accountService->loginByCredentials( $email, (string) $data->get('password'), $context ); // No try/catch — exceptions propagate with distinct codes
This inconsistency confirms the Store API exposure is an oversight, not a design decision.
Rate limiting is present but insufficient for enumeration
The login route has rate limiting (LoginRoute.php:47-51) keyed on strtolower($email) . '-' . $clientIp. This slows bulk enumeration but does not prevent it because:
1. The attacker only needs one request per email to determine existence 2. The rate limit key includes the IP, so rotating IPs resets the counter 3. The rate limiter is designed to prevent brute-force password guessing, not single-probe enumeration
Impact
- Customer email enumeration: An attacker can confirm whether specific email addresses are registered as customers, enabling targeted attacks - Phishing enablement: Confirmed customer emails can be targeted with store-specific phishing campaigns (e.g., fake order confirmations, password reset lures) - Credential stuffing optimization: Attackers with breached credential databases can first filter for valid emails before attempting password guesses, improving efficiency against rate limits - Privacy violation: Confirms an individual's association with a specific store, which may be sensitive depending on the store's nature (e.g., medical supplies, adult products) - Email reflection: The CHECKOUTCUSTOMERNOTFOUND response echoes the probed email in the detail and meta.parameters.email fields, which could be leveraged in reflected content attacks
Recommended Remediation
Option 1: Catch both exceptions in LoginRoute and throw a unified error (Preferred)
Apply the same pattern already used in the storefront controller:
php // src/Core/Checkout/Customer/SalesChannel/LoginRoute.php public function login(#[\SensitiveParameter] RequestDataBag $data, SalesChannelContext $context): ContextTokenResponse { EmailIdnConverter::encodeDataBag($data); $email = (string) $data->get('email', $data->get('username'));
if ($this->requestStack->getMainRequest() !== null) { $cacheKey = strtolower($email) . '-' . $this->requestStack->getMainRequest()->getClientIp();
try { $this->rateLimiter->ensureAccepted(RateLimiter::LOGINROUTE, $cacheKey); } catch (RateLimitExceededException $exception) { throw CustomerException::customerAuthThrottledException($exception->getWaitTime(), $exception); } }
try { $token = $this->accountService->loginByCredentials( $email, (string) $data->get('password'), $context ); } catch (CustomerNotFoundException) { // Normalize to the same exception as bad credentials throw CustomerException::badCredentials(); }
if (isset($cacheKey)) { $this->rateLimiter->reset(RateLimiter::LOGINROUTE, $cacheKey); }
return new ContextTokenResponse($token); }
This ensures both "not found" and "bad credentials" return the same CHECKOUTCUSTOMERAUTHBADCREDENTIALS code and generic message.
Option 2: Unify at the AccountService layer
For defense in depth, change AccountService::getCustomerByLogin() to throw BadCredentialsException instead of letting CustomerNotFoundException propagate:
php // src/Core/Checkout/Customer/SalesChannel/AccountService.php public function getCustomerByLogin(string $email, string $password, SalesChannelContext $context): CustomerEntity { if ($this->isPasswordTooLong($password)) { throw CustomerException::badCredentials(); }
try { $customer = $this->getCustomerByEmail($email, $context); } catch (CustomerNotFoundException) { throw CustomerException::badCredentials(); }
// ... rest of password verification }
This protects all callers of getCustomerByLogin() regardless of how they handle exceptions. Note: getCustomerByEmail() is also called independently (e.g., password recovery), so that method should continue to throw CustomerNotFoundException for internal use — the normalization should happen at the login boundary.
Additional: Fix registration endpoint
The registration endpoint (POST /store-api/account/register) also leaks email existence via CUSTOMEREMAILNOTUNIQUE. For complete remediation, consider returning a generic success response and sending a notification email to the existing address instead.
Credit
This vulnerability was discovered and reported by bugbunny.ai.
Summary
An insufficient check on the filter types for unauthenticated customers allows access to orders of other customers. This is part of the deepLinkCode support on the store-api.order endpoint.
Details
Data Exposure
Depending on the order payload configuration, attackers may retrieve: - Customer names - Billing address - Shipping address - Email addresses - Ordered products - Order values - Order numbers - Order dates - Payment method information - Shipping method information - More customs, depending on the given associations in the request
Security Impact
This vulnerability allows: - Unauthorized access to foreign customer order data - Mass enumeration of recent orders - Potential scraping of customer personal information
Limitation
No limitation, but only orders from the past 30 days are checked for changeable means of payment (unrelated).
Impact
The code is present since ~2021. Likely every version since then is impacted for every store.
Impact We fixed with CVE-2023-2017 Twig filters to only be executed with allowed functions. However there was a regression that lead to an array and array crafted PHP Closure not checked being against allow list for the map(...) override
Patches Patched in 6.7.6.1
Workarounds Install the security plugin
Impact
By exploiting the XSS vulnerabilities, malicious actors can perform harmful actions in the user's web browser in the session context of the affected user. Some examples of this include, but are not limited to: Obtaining user session tokens. Performing administrative actions (when an administrative user is affected). These vulnerabilities pose a high security risk. Since a sensitive cookie is not configured with the HttpOnly attribute and administrator JWTs are stored in sessionStorage, any successful XSS attack could enable the theft of session cookies and administrative tokens.
Description
A request parameter from the URL of the login page is directly rendered within the Twig template of the Storefront login page without further processing or input validation. This allows direct code injection into the template via the URL parameter. An attacker can create malicious links that could be used in a phishing attack. The parameter waitTime lacks proper input validation.
The attack can be tested with the following URL pattern:
/account/login?loginError=1&waitTime=<a%20href%3D"https%3A%2F%2Fde.wikipedia.org%2Fwiki%2FPhishing">Here<%2Fa>
The same applies to the errorSnippet parameter:
/account/login?loginError=1&errorSnippet=Reset%20your%20password%20%3Ca%20href%3D%22https%3A%2F%2Fde.wikipedia.org%2Fwiki%2FPhishing%22%3Ehere%3C%2Fa%3E.
A race condition vulnerability has been identified in Shopware's voucher system of Shopware v6.6.10.4 that allows attackers to bypass intended voucher restrictions and exceed usage limitations.
A stored cross-site scripting (XSS) vulnerability exists in the Shopware 6 installation interface at /recovery/install/database-configuration/. The cdatabaseschema field fails to properly sanitize user-supplied input before rendering it in the browser, allowing an attacker to inject malicious JavaScript. This vulnerability can be exploited via a Cross-Site Request Forgery (CSRF) attack due to the absence of CSRF protections on the POST request. An unauthenticated remote attacker can craft a malicious web page that, when visited by a victim, stores the payload persistently in the installation configuration. As a result, the payload executes whenever any user subsequently accesses the vulnerable installation page, leading to persistent client-side code execution.
Impact
Currently the default settings for double-opt-in allow for mass unsolicited newsletter sign-ups without confirmation.
Default settings are:
Newsletter: Double Opt-in - active
Newsletter: Double opt-in for registered customers - disabled
Log-in & sign-up: Double opt-in on sign-up - disabled
With these settings, anyone can register an account on the shop using any e-mail-address and then check the check-box in the account page to sign up for the newsletter. The recipient will receive two mails confirming registering and signing up for the newsletter, no confirmation link needed to be clicked for either. In the backend the recipient is set to “instantly active”.
Patches Update to Shopware 6.6.10.3 or 6.5.8.17
Workarounds For older versions of 6.4, corresponding security measures are also available via a plugin. For the full range of functions, we recommend updating to the latest Shopware version.
Impact
The Shopware application API contains a search functionality which enables users to search through information stored within their Shopware instance. The searches performed by this function can be aggregated using the parameters in the “aggregations” object. The ‘name’ field in this “aggregations” in nested object is vulnerable SQL-injection and can be exploited using SQL parameters.
Patches
Update to Shopware 6.6.10.3
Workarounds
For older versions of 6.5 or 6.4 corresponding security measures are also available via a plugin. For the full range of functions, we recommend updating to the latest Shopware version.
Credit
Redteam Pentesting
Impact Through the store-api it is possible as a attacker to check if a specific e-mail address has an account in the shop.
Using the store-api endpoint /store-api/account/recovery-password you get the response {"errors":[{"status":"404","code":"CHECKOUTCUSTOMERNOTFOUND","title":"Not Found","detail":"No matching customer for the email \u0022asdasfd@asdads.de\u0022 was found.","meta":{"parameters":{"email":"asdasfd@asdads.de"}}}]}
which indicates clearly that there is no account for this customer. In contrast you get a success response if the account was found.
Patches Update to Shopware 6.6.10.3
Workarounds For older versions of 6.5 or 6.4, corresponding security measures are also available via a plugin. For the full range of functions, we recommend updating to the latest Shopware version.
Impact
It's possible to pass long passwords that leads to Denial Of Service via forms in Storefront forms or Store-API.
Patches Update to Shopware 6.6.10.3 or 6.5.8.17
Workarounds For older versions of 6.4, corresponding security measures are also available via a plugin. For the full range of functions, we recommend updating to the latest Shopware version.
Impact
The Shopware application API contains a search functionality which enables users to search through information stored within their Shopware instance. The searches performed by this function can be aggregated using the parameters in the “aggregations” object. The ‘name’ field in this “aggregations” object is vulnerable SQL-injection and can be exploited using SQL parameters.
Patches
Update to Shopware 6.6.5.1 or 6.5.8.13
Workarounds
For older versions of 6.1, 6.2, 6.3 and 6.4 corresponding security measures are also available via a plugin. For the full range of functions, we recommend updating to the latest Shopware version.
Credit
LogicalTrust
Impact The context variable is injected into almost any Twig Template and allows to access to current language, currency information. The context object allows also to switch for a short time the scope of the Context as a helper with a callable function.
Example call from PHP:
php $context->scope(Context::SYSTEMSCOPE, static function (Context $context) use ($mediaService, $media, &$fileBlob): void { $fileBlob = $mediaService->loadFile($media->getId(), $context); });
This function can be called also from Twig and as the second parameter allows any callable, it's possible to call from Twig any statically callable PHP function/method.
It's not possible as customer to provide any Twig code, the attacker would require access to Administration to exploit it using Mail templates or using App Scripts.
Patches Update to Shopware 6.6.5.1 or 6.5.8.13
Workarounds For older versions of 6.1, 6.2, 6.3 and 6.4 corresponding security measures are also available via a plugin. For the full range of functions, we recommend updating to the latest Shopware version.
Impact
Shopware has a new Twig Tag swsilentfeaturecall which silences deprecation messages while triggered in this tag. It accepts as parameter a string the feature flag name to silence, but this parameter is not escaped properly and allows execution of code.
Patches Update to Shopware 6.6.5.1 or 6.5.8.13
Workarounds For older versions of 6.2, 6.3, and 6.4, corresponding security measures are also available via a plugin. For the full range of functions, we recommend updating to the latest Shopware version.
Impact
The store-API works with regular entities and not expose all fields for the public API; fields need to be marked as ApiAware in the EntityDefinition. So only ApiAware fields of the EntityDefinition will be encoded to the final JSON.
The processing of the Criteria did not considered ManyToMany associations and so they were not considered properly and the protections didn't get used.
This issue cannot be reproduced with the default entities by Shopware, but can be triggered with extensions.
Patches Update to Shopware 6.6.5.1 or 6.5.8.13.
Workarounds For older versions of 6.2, 6.3, and 6.4, corresponding security measures are also available via a plugin. For the full range of functions, we recommend updating to the latest Shopware version.
Impact
When a authentificated request is made to POST /store-api/account/logout, the cart will be cleared, but the User won't be logged out. This affects only the direct store-api usage, as the PHP Storefront listens additionally on CustomerLogoutEvent and invalidates the session additionally.
Patches The problem has been fixed with Shopware 6.6.1.0 and 6.5.8.8.
Workarounds When you are not able to update, you can install the latest version of the Shopware Security Plugin.
Impact
The Symfony Session Handler, pop's the Session Cookie and assign it to the Response. Since Shopware 6.5.8.0 the 404 pages, are cached, to improve the performance of 404 pages. So the cached Response, contains a Session Cookie when the Browser accessing the 404 page, has no cookies yet. The Symfony Session Handler is in use, when no explicit Session configuration has been done. When Redis is in use for Sessions using the PHP Redis extension, this exploiting code is not used.
Patches Update to Shopware version 6.5.8.7
Workarounds Using Redis for Sessions, as this does not trigger the exploit code. Example configuration for Redis
ini php.ini session.savehandler = redis session.savepath = "tcp://127.0.0.1:6379"
Consequences
As an guest browser session has been cached on a 404 page, every missing image or directly reaching a 404 page will logout the customer or clear his cart.
Impact The Shopware application API contains a search functionality which enables users to search through information stored within their Shopware instance. The searches performed by this function can be aggregated using the parameters in the “aggregations” object. The ‘name’ field in this “aggregations” object is vulnerable SQL-injection and can be exploited using time-based SQL-queries.
Patches Update to Shopware 6.5.7.4
Workarounds For older versions of 6.1, 6.2, 6.3 and 6.4 corresponding security measures are also available via a plugin. For the full range of functions, we recommend updating to the latest Shopware version.
Impact
In the Shopware CMS, the state handler for orders fails to sufficiently verify user authorizations for actions that modify the payment, delivery, and/or order status. Due to this inadequate implementation, users lacking 'write' permissions for orders are still able to change the order state.
Patches Update to Shopware 6.5.7.4
Workarounds For older versions of 6.1, 6.2, 6.3 and 6.4 corresponding security measures are also available via a plugin. For the full range of functions, we recommend updating to the latest Shopware version.
Shopware is an open headless commerce platform. The implemented Flow Builder functionality in the Shopware application does not adequately validate the URL used when creating the “call webhook” action. This enables malicious users to perform web requests to internal hosts. This issue has been fixed in the Commercial Plugin release 6.5.7.4 or with the Security Plugin. For installations with Shopware 6.4 the Security plugin is recommended to be installed and up to date. For older versions of 6.4 and 6.5 corresponding security measures are also available via a plugin. For the full range of functions, we recommend updating to the latest Shopware version.
Impact The mail validation in the registration process had some flaws, so it was possible to construct different mail addresses, that in the end result in the same address, which is shared by multiple accounts.
Patches We recommend updating to the current version 5.7.18. You can get the update to 5.7.18 regularly via the Auto-Updater or directly via the release page. https://github.com/shopware5/shopware/releases/tag/v5.7.18
For older versions you can use the Security Plugin: https://store.shopware.com/en/swag575294366635f/shopware-security-plugin.html
References https://docs.shopware.com/en/shopware-5-en/security-updates/security-update-06-2023
Impact Due to a wrong configuration in the .htaccess file, the configuration file of Javascript dependencies could be read in production environments (themes/package-lock.json). With this information, the used Shopware version might be determined by an attacker, which could be used for further attacks.
Patches We recommend updating to the current version 5.7.18. You can get the update to 5.7.18 regularly via the Auto-Updater or directly via the release page. https://github.com/shopware5/shopware/releases/tag/v5.7.18
For older versions you can use the Security Plugin: https://store.shopware.com/en/swag575294366635f/shopware-security-plugin.html
References https://docs.shopware.com/en/shopware-5-en/security-updates/security-update-06-2023
Shopware v5.5.10 was discovered to contain a cross-site scripting (XSS) vulnerability via the recovery/install/ URI.
Impact We fixed with CVE-2023-22731 Twig filters to only be executed with allowed functions. It is possible to pass PHP Closures as string or an array and array crafted PHP Closures was not checked against allow list
Patches The problem has been fixed with 6.4.20.1 with an improved override.
Workarounds For older versions of 6.1, 6.2, and 6.3, corresponding security measures are also available via a plugin. For the full range of functions, we recommend updating to the latest Shopware version.
SwagPayPal is a PayPal integration for shopware/platform. If JavaScript-based PayPal checkout methods are used (PayPal Plus, Smart Payment Buttons, SEPA, Pay Later, Venmo, Credit card), the amount and item list sent to PayPal may not be identical to the one in the created order. The problem has been fixed with version 5.4.4. As a workaround, disable the aforementioned payment methods or use the Security Plugin in version >= 1.0.21.
Shopware is an open source commerce platform based on Symfony Framework and Vue js. In affected versions the log module would write out all kind of sent mails. An attacker with access to either the local system logs or a centralized logging store may have access to other users accounts. This issue has been addressed in version 6.4.18.1. For older versions of 6.1, 6.2, and 6.3, corresponding security measures are also available via a plugin. For the full range of functions, we recommend updating to the latest Shopware version. Users unable to upgrade may remove from all users the log module ACL rights or disable logging.
Shopware is an open source commerce platform based on Symfony Framework and Vue js. The Administration session expiration was set to one week, when an attacker has stolen the session cookie they could use it for a long period of time. In version 6.4.18.1 an automatic logout into the Administration session has been added. As a result the user will be logged out when they are inactive. Users are advised to upgrade. There are no known workarounds for this issue.
Shopware is an open source commerce platform based on Symfony Framework and Vue js. In a Twig environment without the Sandbox extension, it is possible to refer to PHP functions in twig filters like map, filter, sort. This allows a template to call any global PHP function and thus execute arbitrary code. The attacker must have access to a Twig environment in order to exploit this vulnerability. This problem has been fixed with 6.4.18.1 with an override of the specified filters until the integration of the Sandbox extension has been finished. Users are advised to upgrade. Users of major versions 6.1, 6.2, and 6.3 may also receive this fix via a plugin.