Security warning: X-Forwarded-For header contains untrusted client-supplied value
ID: networking/xff-header-spoofed
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| any | active | — | — | — |
Root Cause
The application trusts the X-Forwarded-For header for client IP identification, but clients can inject arbitrary values in this header. This allows IP-based access control bypass, rate limit evasion, and log forgery. The application must only trust XFF values from known trusted proxies.
genericWorkarounds
-
92% success Configure trusted proxy addresses and parse XFF right-to-left, trusting only known proxies
1. Define the list of trusted proxy IPs or CIDR ranges in the application config 2. Parse X-Forwarded-For right-to-left, skipping IPs that match trusted proxies 3. The first non-trusted IP from the right is the real client IP 4. In nginx: set_real_ip_from 10.0.0.0/8; real_ip_header X-Forwarded-For; real_ip_recursive on; 5. In Express.js: app.set('trust proxy', ['loopback', '10.0.0.0/8']) 6. Test by sending a forged XFF header and verifying the application extracts the correct IP -
88% success Use a custom header set by the edge proxy instead of X-Forwarded-For
1. Configure the edge proxy to set a custom header (e.g., X-Real-Client-IP) with the direct client IP 2. Strip any client-supplied X-Real-Client-IP at the edge: proxy_set_header X-Real-Client-IP $remote_addr; 3. Configure the application to use X-Real-Client-IP instead of X-Forwarded-For 4. This header is set only by the trusted edge proxy and cannot be spoofed by clients 5. Ensure no downstream proxy overwrites this header
Dead Ends
Common approaches that don't work:
-
Trust the entire X-Forwarded-For header value without validation
95% fail
Any client can set X-Forwarded-For to an arbitrary IP address. Without validating which proxies in the chain are trusted, the application may use the attacker-controlled leftmost value as the real client IP.
-
Strip X-Forwarded-For at the edge proxy but not configure the application to use the correct header
65% fail
If the edge proxy strips the header but re-adds it with only the direct client IP, the application must be configured to read from this specific proxy's header. Misconfiguration means the application may still read a different header or the wrong position in the chain.