Ce qui se passe
Le 4 novembre 2026, l'équipe Symfony a publié huit avis de sécurité en même temps. Ils sont tous corrigés par les mêmes versions : 5.4.56, 6.4.50, 7.4.23 et 8.1.11 (HtmlSanitizer, apparu en 6.1, n'a pas de 5.4). Les patchs sont aussi reportés sur la 8.2. Aucun des huit avis ne signale d'attaque en cours, et plusieurs ne valent que pour une configuration précise.
| Avis | Composant | Effet |
|---|---|---|
| CVE-2026-118515 | Serializer | UploadedFile construit depuis les données de la requête : n'importe quel fichier du serveur passe pour un envoi |
| GHSA-pxj9-jh84-vhm5 | Serializer | DATA: en majuscules ouvert comme chemin local |
| GHSA-5mx8-mwrp-5693 | HttpFoundation | URL générées vers un hôte choisi par le client |
| GHSA-3h27-hjv7-fqjx | HttpFoundation | Règles placées devant PHP contournées par /index.phpadmin |
| CVE-2026-118513 | Security HTTP | Authentificateur X509 : l'identifiant se lit dans une virgule échappée du CN |
| CVE-2026-118517 | HtmlSanitizer | Liste d'hôtes autorisés contournée par http:evil.example (gravité faible) |
| GHSA-6prc-h956-hxjq | Filesystem | Path prend tout préfixe avant :// pour une racine |
| GHSA-8f57-m8wj-x65w | Security HTTP | Les connexions programmatiques sautent checkPostAuth() |
À lire en premier : cinq avis, trois sujets
1. Un champ UploadedFile désigne un fichier du serveur
DataUriNormalizer ne construit que SplFileInfo, SplFileObject et File. Une propriété typée UploadedFile était
laissée à ObjectNormalizer, qui l'instanciait par son constructeur à partir des données reçues, y compris le chemin
et le drapeau test. Avec #[MapRequestPayload] et un DTO portant une propriété UploadedFile, la requête n'a pas
besoin d'envoyer le moindre fichier : elle nomme un fichier du serveur, et l'application le traite comme un envoi.
Selon l'usage, cela expose tout fichier lisible par PHP, ou le déplace quand move() est appelé comme dans la
documentation. Assert\File n'y change rien, puisqu'il valide le vrai fichier du serveur.
Le cas voisin, GHSA-pxj9-jh84-vhm5, joue sur la casse : l'expression de DataUriNormalizer accepte DATA: ou Data:,
mais PHP n'active son flux data: que pour la forme minuscule. Autrement, il ouvre la chaîne comme un chemin local et
résout les .. : DATA:,/../../../../../../etc/hostname livre le contenu de /etc/hostname. FrameworkBundle
enregistre ce normaliseur par défaut.
2. Des URL générées vers l'hôte de l'attaquant
Quand Request::getBaseUrl() ne trouve pas le nom du script au début de l'URI, il le cherche plus loin et garde tout
ce qui précède, partie que le client choisit. Une URI commençant par // ou /\ donne alors une base qui débute par
un hôte. Sont touchées les applications dont le point d'entrée est dans un sous-dossier, par exemple avec un
.htaccess qui réécrit tout vers public/, ainsi que certaines configurations nginx sans fastcgi_split_path_info et
php -S avec un routeur hors de la racine. Les configurations recommandées par la documentation ne sont pas touchées.
framework.trusted_hosts n'aide pas, l'hôte de la requête étant le vrai.
Même famille, GHSA-3h27-hjv7-fqjx : depuis le correctif de CVE-2025-64500, getPathInfo() retire le nom du script du
début de l'URL même quand il n'est que le début d'un segment plus long. Avec SCRIPT_NAME=/index.php, /index.phpadmin
est routé comme /admin. Les règles de Symfony (access_control, pare-feux) lisent le même chemin et restent
cohérentes ; celles placées devant PHP ne le sont pas : un location /admin nginx, un <Location /admin> Apache ou
une règle de CDN ou de WAF. La configuration nginx de la documentation et le .htaccess de symfony/apache-pack
rendent /index.php/admin inaccessible mais laissent passer /index.phpadmin.
3. Une virgule échappée dans un certificat
CVE-2026-118513, correctif incomplet de CVE-2026-45063 : X509Authenticator cherche emailAddress= dans le DN déjà
sérialisé, sans distinguer une virgule qui sépare deux attributs d'une virgule échappée dans une valeur. Un certificat
dont le CN vaut jdoe,emailAddress=admin@example.com authentifie alors comme admin@example.com. Il faut détenir un
certificat de l'autorité de confiance de l'application et pouvoir influencer le CN. Les applications qui passent un
userKey par attribut, comme SSL_CLIENT_S_DN_Email, ne sont pas touchées.
Les trois autres, en bref
- CVE-2026-118517 :
UrlSanitizerlaissait passerhttp:evil.example(zéro barre),///evil.exampleouhttps://://evil.example/quandallowRelativeLinks(true)s'ajoute à une liste d'hôtes. La configuration par défaut n'est pas touchée. - GHSA-6prc-h956-hxjq : sur 6.4 et plus, un paquet malveillant peut faire écrire
importmap:requireouimportmap:installhors deassets/vendor, par exemplepublic/x:/shell.php. - GHSA-8f57-m8wj-x65w : un compte refusé par
checkPostAuth()(compte expiré) pouvait encore se connecter parSecurity::login(). Après le correctif, l'exception sort delogin(): un contrôleur d'inscription peut devoir la capter.
Comment s'y prendre
composer show 'symfony/*' | grep -E 'http-foundation|serializer|security-http|filesystem|html-sanitizer'
composer update 'symfony/*'Puis relire les DTO qui portent un UploadedFile sous #[MapRequestPayload], et tester /index.phpadmin contre vos
règles d'accès nginx, Apache ou CDN.
Source : le blog Symfony et ses sept autres avis du 4 novembre (GHSA-pxj9, GHSA-5mx8, GHSA-3h27, CVE-2026-118513, CVE-2026-118517, GHSA-6prc, GHSA-8f57). Source en anglais.