Symfony detailed, in an October 9, 2026 post signed by Javier Eguiluz, three security changes arriving with version 8.2, expected in November. All three touch the UriSigner component, used to generate password-reset links, passwordless login links, and email verification links. Taken together, they close design flaws that plenty of PHP applications unknowingly reproduce.
Single-use links via a version argument
The sign(), check(), checkRequest() and verify() methods now accept a $version argument, whose value feeds into the signature without appearing in the URL. In practice, a password-reset link can be signed with the current password hash: once the password changes, the old link no longer verifies, even if it was never clicked.
// Lors de l'envoi de l'email de réinitialisation
$url = $uriSigner->sign(
$this->generateUrl('reset_password', ['id' => $user->getId()], UrlGeneratorInterface::ABSOLUTE_URL),
new \DateInterval('PT30M'),
$user->getPassword(),
);
// Dans le contrôleur qui traite le lien
$uriSigner->verify($request, $user->getPassword());
Expiration becomes mandatory in 9.0
Signing a URL without an expiration date is now deprecated; Symfony 9.0 will make that expiration mandatory. There are two ways to set it: pass it on every call to sign(), or set a default value through the uri_signer service configuration:
framework:
uri_signer:
expiration: 3600
| Change | Status in 8.2 | Status in 9.0 |
|---|---|---|
$version argument (single use) | Available | Unchanged |
| Signed URL expiration | Deprecated without expiration | Mandatory |
| Signed login link parameters | Available via $parameters | Unchanged |
Login links no longer leave parameters in plain sight
Third change: additional query parameters on a login link (a redirect destination, for example) weren’t covered by the signature and could therefore be altered without invalidating the link. createLoginLink() now accepts a $parameters argument that is signed along with the rest of the URL:
$loginLinkDetails = $loginLinkHandler->createLoginLink($user, parameters: [
'return_to' => '/account/settings',
]);
The post flags a detail that’s easy to miss: in the login success handler, the redirect destination must be read from the _login_link_parameters attribute, never from the raw query string. A mail client or a tracking tool can append its own unsigned parameters to the URL; only the ones read through that attribute have been verified.
A reset link that stays valid after use, or carries no expiration date, isn’t a forgotten feature — it’s a design flaw Symfony is finally fixing at the source.
A fix that reaches beyond the framework’s core
These three changes arrive shortly after the KeyManagement component landed in the same 8.2 release, which unifies encryption of sensitive data behind the market’s main KMS providers. Securing signed URLs follows the same logic: taking decisions out of developers’ hands that, left to chance, tend to turn into vulnerabilities. Applications that roll their own signed-link generator instead of going through UriSigner get none of these fixes and remain exposed to the same flaws; an audit on that front usefully complements a broader review of a site’s application security policy.
Key takeaways
Symfony 8.2, expected in November, adds single-use signed links, paves the way for mandatory expiration in version 9.0, and now signs login link parameters. All three fixes target design flaws common on password-reset and passwordless login links.
In code audits for clients, I regularly find password-reset links that stay valid well past their first use, for lack of explicit invalidation on the application side. This fix takes that responsibility out of developers’ hands: once an application upgrades to Symfony 8.2, there’s no reason left to keep a homemade UriSigner workaround for this exact case — Simon Janvier.
Further reading: the official post on the Symfony blog.
