Quand ton app Angular SSR fonctionne… mais ne fait plus de SSR
C’est probablement l’un des pièges les plus subtils introduits récemment avec Angular SSR.
Ton application fonctionne.
Les pages s’affichent.
Aucune erreur visible côté utilisateur.
Et pourtant
tu ne fais plus de rendu côté serveur.
Le mécanisme invisible
Lorsqu’un utilisateur appelle une route SSR :
GET /preview
Host: example.com
Angular SSR reconstruit une URL complète en interne :
[https://example.com/preview](https://example.com/preview)
Ce point est fondamental.
Angular ne travaille pas avec des chemins relatifs, mais avec des URLs absolues, construites à partir du Host de la requête.
Le vrai problème : le Host est une donnée utilisateur
Contrairement à ce que beaucoup pensent :
le header HTTP Host n’est pas une source fiable
C’est une simple donnée envoyée par le client.
Un attaquant peut parfaitement faire :
curl https://your-app/preview -H "Host: evil.com"
Et ton serveur recevra :
Host: evil.com
Angular reconstruira alors :
https://evil.com/preview
La faille : SSRF
Ce comportement ouvre la porte à une attaque bien connue :
SSRF — Server Side Request Forgery
Le principe :
- le serveur fait confiance à une donnée contrôlée par l’utilisateur
- il construit une URL avec cette donnée
- il effectue des appels réseau vers cette URL
Conséquences possibles :
- accès à des services internes
- accès aux metadata cloud (ex: credentials)
- exfiltration de données sensibles
Ce qu’Angular a changé
Pour corriger cela, Angular a introduit une protection :
allowedHosts
Le principe est simple :
Host ∈ allowedHosts → SSR autorisé
Host ∉ allowedHosts → SSR bloqué
Le piège : le fallback silencieux
Aujourd’hui, si le host n’est pas autorisé :
❌ SSR désactivé
✅ fallback en CSR
Dans les logs :
Falling back to client side rendering
- Ton application fonctionne toujours…
- Mais elle ne fait plus de SSR.
Et demain ?
Angular a annoncé un durcissement :
Host non autorisé → HTTP 400
- Plus de fallback.
- Ta requête SSR casse directement.
Conséquence réelle en production
Beaucoup d’applications aujourd’hui :
- pensent faire du SSR
- mais servent en réalité du CSR dans certains cas
Exemples fréquents :
- reverse proxy mal configuré
- host interne utilisé par le load balancer
- headers forwardés incorrectement
- appels internes ou outils de test
La solution
Après mise à jour Angular :
configurer explicitement les hosts autorisés
Exemple :
allowedHosts: [
'example.com',
'www.example.com',
'*.example.com'
]
La vraie leçon (au-delà d’Angular)
Ce problème dépasse Angular.
C’est un problème fondamental du protocole HTTP.
Rappel important
Le Host header n’est pas une garantie d’identité.
C’est une déclaration du client.
Et comme toute déclaration utilisateur :
elle doit être validée.
À retenir
- SSR = backend → mêmes exigences de sécurité qu’une API
- ne jamais faire confiance au
Host - ne jamais construire une URL serveur à partir d’une donnée non validée
- toujours contrôler les entrées, même au niveau protocolaire
Conclusion
Ce n’est pas un bug Angular.
- C’est une conséquence directe du design HTTP.
Et c’est exactement pour ça que comprendre HTTP en profondeur n’est pas optionnel.
Le danger n’est pas dans le path. Le danger est dans le Host.