Symfony detalló, en una entrada del 9 de octubre de 2026 firmada por Javier Eguiluz, tres cambios de seguridad que llegarán con la versión 8.2, prevista para noviembre. Los tres afectan al componente UriSigner, usado para generar enlaces de restablecimiento de contraseña, enlaces de inicio de sesión sin contraseña y enlaces de verificación de correo. En conjunto, cierran fallos de diseño que muchas aplicaciones PHP reproducen sin darse cuenta.
Enlaces de un solo uso gracias a un parámetro de versión
Los métodos sign(), check(), checkRequest() y verify() aceptan ahora un argumento $version, cuyo valor entra en el cálculo de la firma sin aparecer en la URL. En la práctica, un enlace de restablecimiento de contraseña puede firmarse con el hash de la contraseña actual: una vez cambiada la contraseña, el enlace antiguo deja de verificarse, aunque nunca se haya usado.
// 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());
La expiración será obligatoria en la 9.0
Firmar una URL sin fecha de expiración queda ahora obsoleto; Symfony 9.0 hará obligatoria esa expiración. Hay dos formas de definirla: pasarla en cada llamada a sign(), o fijar un valor por defecto mediante la configuración del servicio uri_signer:
framework:
uri_signer:
expiration: 3600
| Cambio | Estado en 8.2 | Estado en 9.0 |
|---|---|---|
Argumento $version (un solo uso) | Disponible | Sin cambios |
| Expiración de las URLs firmadas | Obsoleta sin expiración | Obligatoria |
| Parámetros firmados de los login links | Disponible mediante $parameters | Sin cambios |
Los enlaces de acceso ya no dejan parámetros sin proteger
Tercer cambio: los parámetros de consulta adicionales de un enlace de acceso (por ejemplo, un destino de redirección) no estaban cubiertos por la firma y, por tanto, podían modificarse sin invalidar el enlace. createLoginLink() acepta ahora un argumento $parameters firmado junto con el resto de la URL:
$loginLinkDetails = $loginLinkHandler->createLoginLink($user, parameters: [
'return_to' => '/account/settings',
]);
La entrada señala un detalle fácil de pasar por alto: en el gestor de éxito de inicio de sesión hay que leer el destino desde el atributo _login_link_parameters, nunca desde la query string sin más. Un cliente de correo o una herramienta de seguimiento puede añadir sus propios parámetros no firmados a la URL; solo los leídos mediante ese atributo han sido verificados.
Un enlace de restablecimiento que sigue siendo válido después de usarse, o sin fecha de expiración, no es una funcionalidad olvidada: es un fallo de diseño que Symfony corrige por fin de raíz.
Una corrección que va más allá del núcleo del framework
Estos tres cambios llegan poco después del componente KeyManagement, incorporado en esa misma versión 8.2, que unifica el cifrado de datos sensibles detrás de los principales KMS del mercado. Asegurar las URLs firmadas sigue la misma lógica: quitar de las manos del desarrollador decisiones que, dejadas por defecto, acaban convirtiéndose en fallos. Las aplicaciones que exponen su propio generador de enlaces firmados sin pasar por UriSigner no se benefician de ninguna de estas correcciones y siguen expuestas a los mismos defectos; una auditoría en ese sentido complementa bien una revisión más amplia de la política de seguridad de la aplicación.
Lo que hay que recordar
Symfony 8.2, prevista para noviembre, añade enlaces firmados de un solo uso, prepara la obligatoriedad de la expiración prevista para la versión 9.0 y ahora firma los parámetros de los enlaces de acceso. Las tres correcciones apuntan a fallos de diseño habituales en los enlaces de restablecimiento de contraseña y de acceso sin contraseña.
En auditorías de código para clientes encuentro con regularidad enlaces de restablecimiento de contraseña que siguen siendo válidos mucho después de su primer uso, por falta de invalidación explícita en la aplicación. Esta corrección retira esa responsabilidad de las manos del desarrollador: en cuanto una aplicación actualice a Symfony 8.2, ya no hay motivo para mantener un UriSigner casero para este caso concreto — Simon Janvier.
Para saber más: la entrada oficial en el blog de Symfony.
