Weak Password Recovery Mechanism for Forgotten Password in Sylius - #VU159503
Published: November 5, 2026
Vulnerability details
The vulnerability allows an unauthenticated attacker to make a Sylius shop customer's password-reset e-mail link point to an attacker-controlled domain and capture the reset token when the customer clicks the link. The same URL-generation mechanism also affects links in user-registration, e-mail-verification and order-confirmation e-mails, as well as the logo and homepage links in the shared layout used by every Sylius e-mail.
The vulnerability exists due to ChannelUrlExtension::generateChannelUrl() falling back to UrlHelper::getAbsoluteUrl() when the resolved channel's optional hostname is empty, deriving the scheme and host from the incoming request without host validation. A remote attacker can submit the victim's e-mail address in an unauthenticated request to POST /api/v2/shop/customers/reset-password or the /{_locale}/forgotten-password form with a spoofed Host header to inject the destination domain into the reset link. Exposure requires the hostname-less channel to be resolved for that request and framework.trusted_hosts to be unset, as it is by default. A permissive trusted-host pattern such as .* also allows the attacker-supplied host. The optional channel hostname is empty by default on a single-channel installation unless an administrator supplies it.
A channel without a hostname cannot be matched by Host; SingleChannelContext instead selects it when exactly one channel exists. On a multi-channel store, a spoofed host matches no channel and no e-mail is sent, except that enabling kernel.debug permits channel selection through the _channel_code query parameter. X-Forwarded-Host influences URL generation only when framework.trusted_proxies is configured to trust x-forwarded-host; otherwise it is ignored. Trusted-proxy configuration does not itself validate hostnames, and trusting that header without host validation permits injection even with a correct Host header. Some affected implementations build the link directly in the e-mail template rather than through the extension, but use the same request-host fallback. Asynchronous Messenger delivery remains exposed because e-mails are rendered within the triggering request before being handed to the mailer. The administrator password-reset e-mail is not affected because it builds its link only from the channel hostname.