Skip to content

Releases: shopware/shopware

Release v6.7.12.1

Choose a tag to compare

@fruppel fruppel released this 07 Jul 08:17
6c127cc

Shopware 6.7.12.1 is a patch release that fixes a breaking issue introduced in the previous version, Shopware 6.7.12.0.

Because Shopware 6.7.12.0 is not installable due to this issue, the improvements and fixes from that release are available for the first time in Shopware 6.7.12.1.

We kept the regular release cycle to avoid disrupting continuous integration and versioning for our community. To see everything that has changed since the last patch version before v6.7.12.0, please read the full list of changes for v6.7.12.0.

System requirements

  • tested on PHP 8.2, 8.4 and 8.5
  • tested on MySQL 8 and MariaDB 11

What's Changed

  • fix: Frozen container parameter bag with deprecated cache config (6.7.12.x backport) by Michael Telgmann (@mitelg) in #18066
  • fix(core): compatibility with Twig 3.28 (backport: 6.7.12.x) by @shopware-octo-sts-app[bot] in #18053

Full Changelog: v6.7.12.0...v6.7.12.1

Get in touch

Discuss about decisions, bugs you might stumble upon, etc in our community discord. See you there ;)

Release v6.6.10.20

Choose a tag to compare

@github-actions github-actions released this 07 Jul 13:38
3731a39

Release v6.7.12.0

Choose a tag to compare

@fruppel fruppel released this 07 Jul 08:16
21081b8

Do not install

This release cannot be installed or updated to because it contains a breaking issue discovered shortly after release. Please use v6.7.12.1 instead.

We kept the regular release cycle to avoid disrupting continuous integration and versioning for our community. The changes from this version are still listed below, but they are only available by installing v6.7.12.1, which includes a fix for the issue.

System requirements

  • tested on PHP 8.2, 8.4 and 8.5
  • tested on MySQL 8 and MariaDB 11

Features

Agentic files for sales channels

Sales channels can now publish opt-in agentic files such as /llms.txt and /agents.md.
Merchants can manage these files in the sales channel details, enable them per sales channel, preview the generated content, and add custom notes without replacing the default content provided by Shopware or extensions.

Core ships the initial agentic file family.
The files are rendered from Twig templates, so Shopware, plugins, apps, and themes can contribute or extend content through normal Shopware Twig inheritance.
Extensions can add additional templates under Resources/views/files/agentic/**.twig, including nested paths such as .well-known/*.

The Admin API exposes documented action routes for listing, reading details, and previewing sales-channel files under /api/_action/sales-channel-file/{fileFamily}/{salesChannelId}.

Storefront

Storefront cache hash no longer varies by language

The HTTP cache hash no longer includes the language id for storefront requests, because the storefront language is derived from the resolved domain URL.
Store API requests still include the language id in the cache hash, as the same Store API URL can return different languages via the sw-language-id header.

Central extension point for content before/after list prices

A new template @Storefront/storefront/component/product/list-price-affix.html.twig is rendered inside every list price display (product box, product detail buy widget, advanced pricing table). It replaces the deprecated listing.beforeListPrice / listing.afterListPrice snippets as the single place to inject content around list prices.

Content can be provided in two ways:

  • Without code: create a translation snippet with a custom key and enter that key in the new sales-channel-aware system config settings core.listing.beforeListPriceSnippetKey / core.listing.afterListPriceSnippetKey. The snippet content is rendered sanitized, wrapped in a list-price-affix list-price-affix-{before|after} span.
  • In a theme or plugin: override the block component_list_price_affix_content once; the position variable (before / after) allows position-specific output.

Thumbnail sizes attribute now emits a value for the XXL breakpoint

The auto-generated sizes attribute produced by thumbnail.html.twig now includes a value for the XXL breakpoint. The xxl key is the open-ended top (container / columns), and xl is a closed range bounded by breakpoint.xxl - 1, matching the pattern used by smaller breakpoints. Templates that pass a manual sizes map to sw_thumbnails should add an xxl entry to keep parity.

Use Bootstrap variable for headings spacing

The hard-coded CSS margin-bottom was removed from HTML headlines H1-H6. The bootstrap variable $headings-margin-bottom can now be used to set the bottom spacing of headlines.

Storefront XHR login failures now keep HTTP 403

Storefront requests that require a logged-in customer no longer redirect to the login page for XMLHttpRequests when the customer session is no longer valid.
The original 403 Forbidden response is preserved.
Regular page requests still redirect to the login page.
This prevents expired sessions from creating redirect chains from XHR endpoints to page controllers and fixes the follow-up failure where the redirected XHR request reaches the login page, which does not allow XHR access.
JavaScript clients can now handle the failed unauthenticated XHR response explicitly.

Mail templates can access storefront theme configuration

Mail templates rendered for a sales channel now receive a temporary salesChannelContext and the assigned themeId.
This allows Twig helpers such as theme_config() to resolve storefront theme configuration in mails without replacing the existing core context variable.
The shared MailTemplateRenderContextEvent is dispatched for both sent mails and preview/simulation rendering so extensions can enrich mail template data through one hook.

Google Ads Enhanced Conversions

A new Enhanced Conversions option was added to the Google Analytics integration. When enabled in the sales channel analytics settings, the checkout finish page sends the SHA256-hashed customer email address via gtag('set', 'user_data', ...) to support Google Ads Enhanced Conversions. Email addresses are normalized according to Google's requirements before hashing.

A new enhanced_conversions boolean field was added to SalesChannelAnalyticsDefinition and SalesChannelAnalyticsEntity.

New extensible Twig block page_checkout_finish_enhanced_conversions has been added to finish-details.html.twig.

Country state field visibility in address forms

Storefront address forms now respect the country displayStateInRegistration setting.
When disabled, the country state field is hidden unless forceStateInRegistration is enabled, in which case the required state field is still shown.
During the update, displayStateInRegistration is activated for every country that has at least one configured state/region.
This keeps existing storefront address forms showing their state selector until the setting is disabled explicitly.

Checkout gateway blocked method fallback

Storefront checkout cart and confirm page loading now resolves payment and shipping methods blocked by the checkout gateway before rendering the page.
The fallback method is selected from the checkout gateway response, preferring the sales-channel default method when available and otherwise using the first available method declared by the gateway.

Customer address fields are trimmed on new writes

Customer address fields submitted through storefront registration and address updates are now trimmed before they are written.
This prevents leading or trailing whitespace from being stored in standard address fields such as first name, last name, street, city, and zipcode.

Existing customer address records are not changed.

New contentSelector option for the AlertAriaPlugin

The AlertAriaPlugin now supports a contentSelector option to define the content element inside the aria-live region that is toggled to trigger the screenreader.
It defaults to .alert-content-container. Override it when applying the plugin to custom markup that is not based on the alert template:

<div class="cart-live-update visually-hidden"
     role="status"
     aria-live="polite"
     data-alert-aria="true"
     data-alert-aria-options='{{ { contentSelector: ".cart-live-update-content" }|json_encode }}'>
    <div class="cart-live-update-content">
        {# ... content that should be announced ... #}
    </div>
</div>

API

Plain JSON API includes preserve extension wrappers

The Admin API plain JSON encoder now keeps extension association fields inside the extensions object when they are selected through includes.
For example, including an extension association such as toOne on an entity returns extensions.toOne instead of promoting toOne to the top-level response.
Nested extension entities also respect their own include definitions, so API clients can filter extension payload fields consistently.

Customer email uniqueness is enforced on writes

Admin API and Sync API customer writes now enforce the same non-guest customer email uniqueness rules as the Administration customer form and Store API registration flows.
When core.systemWideLoginRegistration.isCustomerBoundToSalesChannel is disabled, a non-guest customer email must be unique globally.
When the setting is enabled, duplicate non-guest emails are only accepted for customers bound to different sales channels.
Extensions can use Shopware\Core\Checkout\Customer\Validation\CustomerEmailUniqueChecker with CustomerEmailUniqueCheck to apply the same configuration-aware uniqueness rules.

Number range previews can target a concrete number range

The Admin API now supports previewing a persisted number range by id via /api/_action/number-range/{numberRangeId}/preview-pattern.
Use this route when editing an existing number range, because it reads the state for the concrete number_range.id.

The previous type-based preview route /api/_action/number-range/preview-pattern/{type} remains available in 6.7 for backwards compatibility, but is deprecated and will be removed in 6.8.
It can only resolve global number ranges and therefore does not support non-global number range state.
The allocation route /api/_action/number-range/reserve/{type} is unchanged.

Empty sw-* id headers are treated as unset

Admin API and Store API requests now treat empty ID headers such as sw-language-id, sw-currency-id, sw-app-integration-id, and sw-app-user-id the same as missing headers.
Empty values fall back to the default request context instead of being forwarded as invalid UUIDs.
Whitespace-only values are still rejected as malformed IDs.

For cache efficiency, clients should consistently either omit sw-language-id and sw-currency-id or send them empty when they intentionally want default context resolution, because these headers can participate in reverse-proxy cache keys.

...

Read more

Release v6.7.11.1

Choose a tag to compare

@github-actions github-actions released this 23 Jun 09:29
c0adc63

System requirements

  • tested on PHP 8.2, 8.4 and 8.5
  • tested on MySQL 8 and MariaDB 11

What's Changed

  • fix: depend on ClientRepositoryInterface in McpAuthenticationListener (backport: 6.7.11.x) by @shopware-octo-sts-app[bot] in #17535
  • fix: Improve import map generation (backport: 6.7.11.x) by @shopware-octo-sts-app-2[bot] in #17531
  • fix: consider footer navigation tree children as page urls (backport: 6.7.11.x) by @shopware-octo-sts-app-2[bot] in #17580

Full Changelog: v6.7.11.0...v6.7.11.1

Get in touch

Discuss about decisions, bugs you might stumble upon, etc in our community discord. See you there ;)

Release v6.7.11.0

Choose a tag to compare

@fruppel fruppel released this 16 Jun 12:54

System requirements

  • tested on PHP 8.2, 8.4 and 8.5
  • tested on MySQL 8 and MariaDB 11

Features

[Experimental] MCP Server for AI tool integration

Shopware now includes an experimental MCP (Model Context Protocol) server that lets AI clients like Claude Desktop or Cursor interact with your Shopware instance through a standardized protocol.

The server exposes the full MCP capability set:

  • Tools for entity management (search, read, create, update, delete), system configuration, state machine transitions, cache management, and storefront product search with sales channel context.
  • Prompts that give the AI client context about Shopware's data model, criteria format, and best practices.
  • Resources that expose static reference data (entity list, sales channels, state machines, business events, flow actions) as readable URIs.

All operations respect the authenticated user's ACL permissions and integrate with the Admin API authentication. Integration credentials can be passed directly via sw-access-key and sw-secret-access-key headers. No separate OAuth token exchange is required. Per-integration allowlists are configurable under Settings -> Integrations to limit which tools, prompts, and resources a given client can see.

To enable this feature, set the MCP_SERVER feature flag to true. The MCP endpoint is available at /api/_mcp and uses the Streamable HTTP transport. Plugins register additional MCP capabilities by tagging services with mcp.tool, mcp.prompt, or mcp.resource. Apps can declare them in their app manifest.

A debug:mcp CLI command is available to list all registered MCP tools, prompts, and resources.

API

New foreign key resolvers for the Sync API

The Sync API now ships seven additional foreign key resolvers, allowing payloads to reference entities by stable human-readable keys instead of UUIDs:

  • currency.iso_code — resolves a currency by its isoCode (e.g. EUR).
  • locale.code — resolves a locale by its code (e.g. en-GB). The en_GB underscore variant is also accepted.
  • payment_method.technical_name — resolves a payment_method by its technicalName.
  • shipping_method.technical_name — resolves a shipping_method by its technicalName.
  • document_type.technical_name — resolves a document_type by its technicalName.
  • salutation.salutation_key — resolves a salutation by its salutationKey (e.g. mr).
  • tax.tax_rate — resolves a tax by its taxRate. Because tax_rate is not unique, the resolver only resolves a value when exactly one tax row matches the given rate; ambiguous rates are left unresolved (combine with nullOnMissing: true if appropriate).

Use these inside a Sync payload anywhere a UUID is expected, e.g. {"currencyId": {"resolver": "currency.iso_code", "value": "EUR"}}.

Mail template preview and send routes support richer rendering context

The mail template Admin API now exposes dedicated preview and send routes:

  • /api/_action/mail-template/simulate
  • /api/_action/mail-template/preview
  • /api/_action/mail-template/get-data-and-send
  • /api/_action/mail-template/available-variables

The preview routes support sales-channel-aware rendering.
/api/_action/mail-template/preview accepts salesChannelId, includeHeaderFooter, and strictRendering, and /api/_action/mail-template/simulate accepts salesChannelId and strictRendering.
This allows Administration extensions and custom tooling to preview the final mail output, including sales-channel-specific headers and footers, against the same rendering context used for sending.

/api/_action/mail-template/get-data-and-send lets callers resolve a persisted mail template together with entity-based template data before sending.
/api/_action/mail-template/available-variables exposes the variable tree for a business event so extensions can build mail-template editing and preview tooling without hardcoding the available data shape.

The /api/_action/mail-template/send payload now also has a first-class extensions bag for custom mail data.
Arbitrary unknown top-level keys are still forwarded for backwards compatibility in 6.7, but they are deprecated and will stop being forwarded in Shopware 6.8.

Core

Backward compatible invalid locales

Added and deprecated BackwardCompatibleNumberFormatter to temporarily allow invalid locale strings without throwing exceptions in PHP >=8.4. It will be removed in Shopware 6.8.

Configurable order deep link expiry

The number of days an order can be accessed via deep link is now configurable via shopware.yaml:

shopware:
  order:
    deep_link:
      expire_days: 30

Technical media associations can be ignored by media:delete-unused

Plugins can now mark technical media associations with the new DAL flag IgnoreInUnusedMediaSearch.
This prevents media:delete-unused from treating metadata-only extensions as real media usage and helps avoid false negatives when removing unused files.
Third-party developers should add this flag to media associations that store technical metadata but do not represent an actual assignment of the media file.

State machine transitions are locked per entity

State machine transitions now acquire a short-lived lock per entity and context version while the current state is read and the transition history is written.
This prevents concurrent calls to StateMachineRegistry::transition() from creating duplicate history entries for the same entity transition.
Extensions that use the registry automatically benefit from the lock; direct SQL or DBAL writes to state fields remain outside this protection.

Deprecation of RegisterScheduleTaskMessage

The RegisterScheduleTaskMessage class and the accompanying message handler RegisterScheduledTaskHandler is deprecated and will be removed in Shopware 6.8.0.0, as the message wasn't dispatched anymore.
If you dispatched that message manually, you should call the TaskScheduler::registerTask() method directly instead.

Plugin snippet files are no longer silently dropped when any translation is installed

Plugin snippet files (.json files shipped in Resources/snippet/) were being skipped for all locales as soon as a core translation for any single locale was installed via the translation installer.
Installing pl-PL for one plugin would cause de-DE, en-GB, and every other locale to lose that plugin's translations entirely, even though no core translation for those locales existed.

The guard in SnippetFileLoader now checks whether a core translation exists for the specific locale being loaded, not for the plugin as a whole.

If you have decorated AbstractTranslationLoader, override the new pluginTranslationExistsForLocale(Plugin $plugin, string $locale): bool method to provide locale-aware behaviour.
The old pluginTranslationExists(Plugin $plugin) is deprecated and will be removed in v6.8.0.

Composer-managed plugins in TestBootstrapper::addActivePlugins()

TestBootstrapper::addActivePlugins() can now be used with Composer-managed plugins installed below vendor/.
Plugins no longer need to be copied into custom/plugins or custom/static-plugins just to be installed and activated during test bootstrap.
When TestBootstrapper::getPluginPath() or getClassLoader() is used without bootstrapping the full application, local plugins below custom/plugins and custom/static-plugins are still resolved from the filesystem.
This keeps static analysis and other tooling that only needs plugin paths or autoload-dev registration working without a database-backed kernel.

Requirement-aware plugin installation order

plugin:install now orders the selected plugins by their Composer plugin requirements before installation.
When one selected plugin requires another selected plugin package, the required plugin is installed first.
This ordering only applies to plugins that are known before the command starts.
The command does not reload Composer's autoloader while it is running.
If installing one plugin also installs new PHP packages, plugins installed afterwards in the same command cannot use those packages yet.
Run those installs in separate CLI calls when a plugin depends on code that another plugin adds through Composer during installation.

Listing configured translations via translation:list

A new translation:list console command prints every locale configured for translation:install / translation:update, including its localized name, English name, and the timestamp of the last installed Crowdin snapshot.
translation:install without --all or --locales now drops into an interactive multi-select prompt with autocompletion over the available locale codes, instead of throwing an exception.

Support for pseudo-locales in translation:install

The new SnippetPatterns::ALLOWED_PSEUDO_LOCALES and SnippetPatterns::PSEUDO_LOCALE_TERRITORY constants register Crowdin pseudo-languages (e.g. ach-UG) as valid translation targets for in-context proofreading and translatability audits.
Pseudo-locales bypass Symfony Intl validation in Language::validateLocale and TranslationLoader::getLocalePath, and a missing locale entity is auto-created on install with a display name from the constant map and a fixed Pseudo Language territory.

Administration

Block renaming

Due to misleading block names, the following blocks have been deprecated and will be removed in v6.8.0. Use the respective replacements instead:

  • sw_settings_listing_option_base_smart_content -> sw_settings_listing_option_base_content
  • sw_settings_listing_option_base_smart_content_general_info -> sw_settings_listing_option_base_content_general_info
  • `sw_settings_listing_option_base_smart_bar_actions_...
Read more

Release v6.6.10.19

Choose a tag to compare

@github-actions github-actions released this 16 Jun 14:27
54ec156

See the UPGRADE.md for all important technical changes.

Release v6.5.8.19

Choose a tag to compare

@github-actions github-actions released this 02 Jun 13:51
54795b4

This patch release contains a security fix in Twig. It is recommended to update your system as soon as possible!

IMPORTANT:
Please note that the security plugin can not save your installation as usual in this case. Instead, a Twig update is necessary which is rolled out with this patch release. This is why this patch release is an absolute exception.

Although version 6.5 is no longer supported, we've published this patch release as a courtesy. You can find more information here: https://developer.shopware.com/release-notes/

System requirements

  • tested on PHP 8.2 and 8.4
  • tested on MySQL 8, MariaDB 11

Fixed bugs

See the UPGRADE.md for all important technical changes.

Full Changelog: v6.5.8.18...v6.5.8.19

Credits

Thanks to all diligent friends for helping us make Shopware better and better with each pull request!

Get in touch

Discuss about decisions, bugs you might stumble upon, etc in our community discord. See you there ;)

Release v6.7.10.2

Choose a tag to compare

@github-actions github-actions released this 01 Jun 09:59
76072b0

System requirements

  • tested on PHP 8.2, 8.4 and 8.5
  • tested on MySQL 8 and MariaDB 11

What's Changed

  • fix: export temporary url file download missing filename (backport: 6.7.10.x) by @shopware-octo-sts-app-2[bot] in #16664
  • fix: update meteor-component-library version and add test for inheritance removal in disabled fields (backport: 6.7.10.x) by @shopware-octo-sts-app[bot] in #16682
  • fix: grant product_translation:read permission in sw-product ACL (backport: 6.7.10.x) by @shopware-octo-sts-app-2[bot] in #16774
  • fix: add sales channel tracking customer privilege (backport: 6.7.10.x) by @shopware-octo-sts-app[bot] in #16786
  • chore: Update Twig and Symfony due to security releases (backport: 6.7.10.x) by @shopware-octo-sts-app[bot] in #16960
  • chore: adjust migrations and fix issue with MariaDB defaults (backport: 6.7.10.x) by @shopware-octo-sts-app-2[bot] in #16955
  • fix: reuse existing media when importing app payment method icons (backport: 6.7.10.x) by Martin Krzykawski (@MartinKrzykawski) in #17085

Full Changelog: v6.7.10.0...v6.7.10.2

Get in touch

Discuss about decisions, bugs you might stumble upon, etc in our community discord. See you there ;)

Security Release v6.6.10.18

Security Release v6.7.10.1

Choose a tag to compare

@github-actions github-actions released this 19 May 16:07
4dc2435

System requirements

  • tested on PHP 8.2, 8.4 and 8.5
  • tested on MySQL 8 and MariaDB 11

Critical Fixes

SVG uploads validate against a strict passive allowlist

SVG uploads in the media subsystem are now validated against a strict passive SVG allowlist before persistence.
Active content such as scripts, event handlers, processing instructions, external references, and URL-based references in attributes are rejected.

The default allowlist covers the W3C SVG2 presentation attribute set (https://www.w3.org/TR/SVG2/attindex.html#PresentationAttributes), ARIA accessibility attributes, the lang and xml:lang accessibility attributes, and the common safe structural elements a, image, marker, metadata, switch, symbol, and view. Anchor href / xlink:href references remain restricted to local document fragments (#id), so javascript:, data:, and remote URLs are rejected. Active content (scripts, event handlers, animations, foreign objects, processing instructions, DOCTYPEs, entities) and any external url(...) / @import references remain blocked regardless of the attribute that carries them.

The accepted SVG subset can be adjusted on installation level via shopware.media.svg.allowed_elements, shopware.media.svg.allowed_attributes, and shopware.media.svg.allowed_reference_attributes in shopware.yaml.

external-link endpoint URL validation aligned with upload-from-url

The URL validation for the external-link endpoint is now in line with the existing validation in the upload-from-url flow.
The static MediaUploadService::validateExternalUrl() is deprecated in favour of the new assertValidExternalUrl() method on the service.
See UPGRADE-6.8.md for migration details.

What's Changed

Full Changelog: v6.7.10.0...v6.7.10.1

Get in touch

Discuss about decisions, bugs you might stumble upon, etc in our community discord. See you there ;)