
Local Go PoC demonstrating CVE-2026-72815, an X-Forwarded-For IP spoofing flaw in go-chi/chi middleware.RealIP that bypasses IP-based ACLs, with a v5.3.0 fixed comparison.
middleware.RealIP IP Spoofing PoCThis repository contains a local Proof of Concept (PoC) for CVE-2026-72815 (GHSA-3fxj-6jh8-hvhx), an IP spoofing vulnerability in go-chi/chi's middleware.RealIP.
The vulnerable middleware blindly trusts the first (leftmost) value of the X-Forwarded-For header and overwrites http.Request.RemoteAddr with it. If a client-controlled forwarding header reaches the application, an attacker may spoof an arbitrary source IP and potentially bypass IP-based ACLs or rate limits, or forge audit log entries.
The PoC uses only Go's httptest package. It does not send requests to external hosts.
Use this project only for educational purposes and authorized security testing. Do not use it against systems without permission.
github.com/go-chi/chi/v5middleware.RealIP>= 5.2.1, < 5.3.05.3.0When X-Forwarded-For is present, middleware.RealIP takes the first comma-separated value and uses it as RemoteAddr.
Conceptually:
if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
ip, _, _ = strings.Cut(xff, ",")
}
r.RemoteAddr = ip
A reverse proxy commonly appends the actual source IP to an existing XFF chain. Therefore, the leftmost value can be attacker-controlled. For example:
X-Forwarded-For: 127.0.0.1, 203.0.113.50
The vulnerable RealIP middleware treats 127.0.0.1 as the client IP.
cd vulnerable
GOWORK=off go run .
The PoC simulates 203.0.113.50 as the real client and 127.0.0.1 as an administrator IP allowed by an ACL.
A normal request is denied with HTTP 403. A spoofed request supplies:
X-Forwarded-For: 127.0.0.1, 203.0.113.50
RealIP rewrites RemoteAddr to 127.0.0.1, causing the same request to receive HTTP 200.
Expected key output:
=== CVE-2026-72815 vulnerable case ===
[*] go-chi/chi version: v5.2.1
[*] normal request status: 403
[*] spoofed request status: 200
[!] VULNERABLE: attacker-controlled X-Forwarded-For bypassed the IP ACL.
cd fixed
GOWORK=off go run .
v5.3.0 introduced ClientIPFromHeader, ClientIPFromXFF, ClientIPFromXFFTrustedProxies, and ClientIPFromRemoteAddr as explicit replacements for RealIP.
The fixed example models a deployment with exactly one trusted reverse proxy that appends the actual client IP to the XFF chain. It therefore uses ClientIPFromXFF(). With the same spoofed input, the rightmost 203.0.113.50 is selected and the ACL remains denied.
Expected key output:
=== CVE-2026-72815 safe replacement case ===
[*] go-chi/chi version: v5.3.0
[*] normal request status: 403
[*] spoofed request status: 403
[+] SAFE: the spoofed leftmost X-Forwarded-For value did not bypass the IP ACL.
bash scripts/run-version-matrix.sh
For backward compatibility, the legacy middleware.RealIP behavior still exists in v5.3.0. It is deprecated and documentation directs users to the new ClientIPFrom* APIs.
Therefore, upgrading the dependency alone is not sufficient if an application continues to use middleware.RealIP. Migrate to the ClientIPFrom* middleware that matches the actual network and reverse-proxy topology.
This repository demonstrates only:
middleware.RealIP;RemoteAddr rewrite; andIt does not scan networks, contact third-party services, perform denial of service, or establish persistence.
middleware.RealIP with the appropriate ClientIPFrom* middleware for your infrastructure.