- headi replays a request with 23 different HTTP headers and diffs the response — flagging access-control bypasses, internal-IP leaks, and Host-header SSRF in seconds.
- A look at why this small Go tool keeps showing up in bug-bounty workflows.
TL;DR
headi is a tiny Go CLI by mlcsec that replays a target URL with 23 different HTTP headers (X-Forwarded-For, Host, X-Real-IP, X-Original-URL, and friends), injects internal-IP payloads, and diffs each response against a baseline. Green output means something changed — usually a 403 turning into a 200, or an internal page bleeding through a reverse proxy. ~281 stars, MIT-style open source, install in one line: go install github.com/mlcsec/headi@latest.
What it actually does
The premise is unsexy and effective. Web apps frequently make trust decisions on client-supplied headers — "if X-Forwarded-For is internal, allow access to /admin" — and reverse proxies, CDNs, and load balancers add their own layer of header rewriting on top. headi automates the dumb-but-necessary first step: try every header that might matter, with every payload that might be whitelisted, and tell you which combinations make the server respond differently.
It is not a scanner. It is a baseline-diffing fuzzer with a curated wordlist. The whole tool is a single Go binary with three flags.
Technical facts
| Property | Value |
|---|---|
| Language | Go (97%) + Makefile |
| Default headers | 23 |
| Default payloads | 127.0.0.1, localhost, internal IP set |
| CLI flags | -u (URL), -p (payload file), -t (timeout) |
| Output | Color-coded: green = response differs from baseline |
| Install | go install github.com/mlcsec/headi@latest |
| Repo metrics | ~281 stars, 56 forks, 43 commits |
The default header list is the entire reason to use it. It covers the full OWASP Host-header testing checklist plus the proxy-aware variants people forget:
Client-IP, Forwarded, From, Host, Origin, Referer, True-Client-IP, X-Client-IP, X-Custom-IP-Authorization, X-Forward-For, X-Forwarded-For, X-Forwarded-Host, X-Forwarded-Server, X-Host, X-HTTP-Host-Override, X-Original-URL, X-Originating-IP, X-Real-IP, X-Remote-Addr, X-Remote-IP, X-Rewrite-URL, X-Wap-Profile, Contact, Connection
How it stacks up
| Tool | Scope | Best for |
|---|---|---|
| headi | 23 headers, baseline diff, single binary | 30-second triage on a new target |
| enumXFF.py / generateIPs.py | X-Forwarded-For only, IP enumeration | Brute-forcing whitelisted IP ranges |
| Burp Intruder + Param Miner | Manual, full request control | Deep dives, post-triage exploitation |
ffuf with header wordlist | Generic fuzzing | Custom payloads, larger wordlists |
The trade-off is obvious: headi wins on speed-to-first-finding. Burp wins on everything else once you know where to dig.
Where this earns its keep
- 403 bypass on internal endpoints.
/admin,/debug,/metricsbehind an IP allow-list — flipX-Forwarded-For: 127.0.0.1orX-Custom-IP-Authorization: 127.0.0.1and watch the green output appear. - Host-header SSRF on shared infrastructure. Reverse proxies that route by Host can be tricked into proxying to internal vhosts:
Host: internal.corp.local. - Password-reset poisoning. If the app uses the incoming Host header to build reset URLs, an attacker-controlled Host means the reset link goes to the attacker.
- Cache poisoning. When Host reflects unencoded into the response body, a reflected vuln becomes a stored one for every user behind the cache.
- Virtual-host brute-forcing. Enumerate internal subdomains by varying
HostandX-Forwarded-Hostagainst a known IP.
The Shubham Shah writeup documented a real wp-admin bypass where repeating the whitelisted IP four times in X-Forwarded-For defeated .htaccess rules — exactly the kind of finding headi surfaces in seconds.
Limitations & pricing
Free, MIT-style, no SaaS. The catch:
- It flags differences, not vulnerabilities. Every green hit needs manual verification — a 200 might still be a generic redirect or a misconfigured error page.
- Single-request replay only. No session handling, no chained flows, no post-auth fuzzing.
- TLS verification stays on by default — toggling
InsecureSkipVerifyrequires editing source, not a flag. - No rate-limit controls beyond
--timeout. Easy to hammer targets if you wrap it in a loop. - Authorized testing only. Bug-bounty scope, your own infra, or written engagement letter — anything else is illegal in most jurisdictions.
- Repo is community-maintained and slow-moving (43 commits total). Forks (56) often carry useful patches.
What this means for your workflow
If your recon stack already has Burp and a half-dozen Go tools, headi slots in as the cheap first pass before you commit to an attack plan. The 23-header list alone is worth keeping around as a wordlist even if you never run the binary — paste it into Intruder, into nuclei templates, or into your own scripts. The tool's real contribution is reminding pentesters that header-based access control still ships in production in 2026, and that a 30-second baseline diff catches it more often than anyone wants to admit.
Sources: github.com/mlcsec/headi, PortSwigger Web Security Academy, shubs.io, OWASP Testing Guide.

