Shopware: The Administration Password Reset Link Follows the Host Header

The link in the genuine reset email is derived from the request host, which an anonymous caller sets freely.

Advisory ID: TP-2026-095
Product: Shopware (e-commerce platform, Symfony and PHP)
Vulnerability type: Weak password recovery mechanism (CWE-640)
CVE: requested (GitHub CNA), assignment pending
CVSS 3.1: 9.3 (Critical) · CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N
Affected versions: <= 6.6.10.22 and 6.7.0.0 through 6.7.13.0
Vendor advisory: GHSA-xj2c-8fw5-mr6m
Fixed in: 6.6.10.23 and 6.7.13.1
Reported: 10 July 2026

Summary

Shopware's Administration offers a password recovery that sends the reset link by email. The host in that link comes from the incoming HTTP request and is not checked against a list of permitted names. The triggering endpoint requires no authentication, so any attacker who sets the Host header causes a reset email to be sent to a known administrator address. The email is genuine, comes from the right Shopware instance and carries its branding, only its link points at the attacker's domain. If the administrator opens the link, they hand the reset hash to the attacker, who then sets the password and gains full Administration access.

Root cause

UserRecoveryService assembles the reset URL through the Symfony router and appends the hash (Core/System/User/Recovery/UserRecoveryService.php:84 and :90). Symfony populates the RequestContext host from the incoming request, and Shopware pins neither default_uri nor request_context.host. The shipped configuration sets framework.router.trusted_hosts: ~ and therefore permits any host (src/Core/Framework/Resources/config/packages/framework.yaml:13). The triggering endpoint POST /api/_action/user/user-recovery carries auth_required => false and is thus reachable entirely anonymously (Core/System/User/Api/UserRecoveryController.php:27). The customer reset path in the storefront is not affected, because it uses the validated sales-channel domains; only the Administration path derives the host from the request.

Proof of Concept

# 1. anonymously, with the Host header set:
POST /api/_action/user/user-recovery
Host: attacker.example
{"email": "<the administrator's address>"}
-> 200

# 2. Shopware sends a genuine reset email to the administrator:
#    http://attacker.example/admin#/login/user-recovery/<hash>

# 3. if the administrator opens the link, the hash reaches the attacker.
#    set the password anonymously:
PATCH /api/_action/user/user-recovery/password
{"hash": "<hash>", "password": "...", "passwordConfirm": "..."}

The workaround without updating is to enable Symfony's trusted-host validation or to configure the web server to reject unexpected Host headers.

Impact

  • Takeover of an Administration account by an anonymous attacker who need only know the matching email address.
  • A considerably higher success rate than phishing, because the email is genuine, comes from the right instance and arrives within the expected flow.
  • Full access to the shop's Administration after takeover, including order and customer data.
  • Affected are installations that pass the request host through, which the official image and the usual reverse proxy configuration both do.

References

Is Something Like This in Your Software?

Our team found this vulnerability in the course of its work. Have your applications tested by the same specialists, with a penetration test from turingpoint.