Host Header Injection
Host Header Injection tricks web applications into using an attacker-controlled domain when generating absolute URLs — poisoning password reset links, cache entries, and redirects to redirect victims to attacker infrastructure.
What Is Host Header Injection?
Web applications often use the Host header to generate absolute URLs — for password reset links, redirects, and canonical URLs. If the application trusts the Host header without validating it against a whitelist, an attacker can inject an arbitrary domain and poison the generated URLs.
How It Works
Password Reset Link Poisoning
A user requests a password reset. The server generates the reset link using the Host header:
POST /forgot-password HTTP/1.1
Host: attacker.com ← attacker-controlled
Content-Type: application/json
{"email": "victim@example.com"}The server sends an email containing:
Click to reset your password:
https://attacker.com/reset?token=abc123
The victim clicks the link, goes to attacker.com, and the attacker captures the reset token — taking over the account without knowing the current password.
Cache Poisoning via Host Header
GET / HTTP/1.1
Host: target.com
X-Forwarded-Host: evil.comIf the app reflects the host into the response (e.g., in canonical URLs or script paths) and a CDN caches the response keyed only by Host: target.com, all users receive the poisoned response.
Response Header Injection
GET /redirect HTTP/1.1
Host: target.com\r\nX-Injected: maliciousCRLF sequences in the Host header can inject arbitrary HTTP response headers in some frameworks.
Real-World Impact
- Account takeover — password reset tokens delivered to attacker's domain
- Phishing — official password reset emails pointing to attacker infrastructure
- Cache poisoning — poisoned canonical URLs served to all users
- WAF bypass — internal routing based on
Hostheader bypasses access controls
How to Fix
Always use a hardcoded base URL from configuration — never from the request:
# Wrong — trusts the Host header
reset_url = f"https://{request.headers.get('Host')}/reset?token={token}"
# Right — uses configured base URL
reset_url = f"{settings.BASE_URL}/reset?token={token}"// Wrong
const resetUrl = `${req.protocol}://${req.get('host')}/reset?token=${token}`
// Right
const resetUrl = `${process.env.BASE_URL}/reset?token=${token}`Validate Host header against a whitelist at the framework level:
# FastAPI middleware
ALLOWED_HOSTS = {"myapp.com", "www.myapp.com", "api.myapp.com"}
@app.middleware("http")
async def validate_host(request: Request, call_next):
host = request.headers.get("host", "").split(":")[0]
if host not in ALLOWED_HOSTS:
return Response("Invalid host", status_code=400)
return await call_next(request)# nginx — reject requests with unexpected Host headers
server {
listen 443 ssl;
server_name myapp.com www.myapp.com;
if ($host !~* ^(myapp\.com|www\.myapp\.com)$) {
return 444;
}
}Strip X-Forwarded-Host at the load balancer unless you specifically need it:
proxy_set_header X-Forwarded-Host "";What VibeWShield Detects
VibeWShield's Host Header Injection scanner injects a canary subdomain (canary-<uuid>.evil.com) into Host, X-Forwarded-Host, and X-Host headers, then scans all response headers and body for its presence. It also tests password reset flows for link poisoning.
Findings are flagged as High with the exact header, canary value, and location where it appeared in the response.
Free security scan
Test your app for Host Header Injection
VibeWShield automatically checks for Host Header Injection and 40+ other vulnerabilities using 63 scanners — in under 3 minutes, no signup required.
Scan your app free