Forwarded Headers Are Not Trusted Input: X-Forwarded-For, Proto and Host Behind a Tunnel
When you put an app behind a tunnel, three request headers start deciding what your code believes. X-Forwarded-For says who is calling, X-Forwarded-Proto says whether the request was HTTPS, and X-Forwarded-Host says which hostname the caller asked for. Configure trust wrongly and you get one of two failures. The harmless one is a redirect loop, or a rate limiter that sees a single visitor. The harmful one is an attacker choosing the values your security checks depend on. 2026 made the second failure concrete. Fastify shipped two CVEs in five months over exactly this problem, and the proxy-addr package behind Express's req.ip had a critical trust-subnet bug of its own. This guide covers what a tunnel really sends, why apps misread it, and the settings that work in Express, Fastify, Django and Rails. What a tunnel actually sends A tunnel changes the shape of the connection. The visitor's TLS session ends at the provider's edge. The edge forwards the request through t...