## https://sploitus.com/exploit?id=96BA85C0-9261-5C52-BC77-CE0531979D65
# CVE-2026-72815: go-chi/chi `middleware.RealIP` IP Spoofing PoC
[English version](README.en.md)
## Summary
This repository contains a local Proof of Concept (PoC) for the IP spoofing vulnerability **CVE-2026-72815** (GHSA-3fxj-6jh8-hvhx) in the `middleware.RealIP` of go-chi/chi. The vulnerable `RealIP` middleware`X-Forwarded-For`’s first value and uses it to overwrite `http.Request.RemoteAddr`. When clients can specify `X-Forwarded-For`, attackers can send any IP address as the source, potentially circumventing IP-based ACLs, rate limits, and audit logs. This PoC only uses `httptest` and does not involve communication with external hosts.
## Conditions
Please use this for educational purposes and authorized security testing only. Do not use it on third-party environments without permission.
## Details of the Vulnerability
- **CVE ID:** CVE-2026-72815
- **GitHub Advisory:** GHSA-3fxj-6jh8-hvhx
- **Product:** `github.com/go-chi/chi/v5`
- **Vulnerable API:** `middleware.RealIP`
- **Type:** Authentication Bypass by Spoofing (CWE-290)
- **CVSS v4.0:** 6.9 (Moderate)
- **Impact versions according to CVE records:** `>= 5.2.1, < 5.3.0`
- **Fixed version:** `5.3.0`
### Root Cause
When `middleware.RealIP` receives `X-Forwarded-For`, it extracts the first value separated by commas and sets it to `RemoteAddr`. Conceptually, this works like this:
```go
if xff:= r.Header.Get("X-Forwarded-For"); xff!= ""
{
ip, _, _ = strings.Cut(xff, ",")
}
```
Typically, a reverse proxy appends the actual source IP at the end of the `X-Forwarded-For` header. Therefore, if an attacker can specify a value like `X-Forwarded-For: 127.0.0.1, 203.0.113.50`, the leftmost value cannot be trusted.
The vulnerable `RealIP` will assume `127.0.0.1` as the client IP.
## PoC
### Required Environment
- Go 1.20 or later
- Network connectivity required for the initial module download
### 1. Reproduction of the vulnerable version v5.2.1
```bash
cd vulnerable
GOWORK=off go run.
```
The PoC assumes that the actual client is `203.0.113.50` and the allowed IP as the administrator is `127.0.0.1`. Normally, the request would result in a HTTP 403 error. However, with the following header, `RealIP` will replace `RemoteAddr` with `127.0.0.1`, resulting in an HTTP 200 response:
```
X-Forwarded-For: 127.0.0.1, 203.0.113.50
```
Expected Main Output:
```
=== CVE-2026-72815 vulnerable case ===
[*] go-chi/chi version: v5.2.1
[*] Normal request status: 403
[*] Spoofed request status: 200
```
### Vulnerability: The attacker-controlled X-Forwarded-For header bypassed the IP ACL
Vulnerable: The attacker-controlled X-Forwarded-For header bypassed the IP ACL.
### Using v5.3.0 with secure APIs
```bash
cd fixed
GOWORK=off go run.
```
In v5.3.0, `ClientIPFromHeader`, `ClientIPFromXFF`, `ClientIPFromXFFTrustedProxies`, and `ClientIPFromRemoteAddr` are added as alternatives to `RealIP`. This PoC case assumes that there is a trusted proxy at the server’s front end, which appends the real client IP to the end of the XFF header. Therefore, `ClientIPFromXFF()` is used. Even if the same forged header is sent, the value `203.0.113.50` at the right end will be accepted, preventing the ACL from being bypassed. Expected output:
```text
=== 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.
```
### Combining both cases
```bash
bash scripts/run-version-matrix.sh
```
## Notes on v5.3.0
Even in v5.3.0, the behavior of the old `middleware.RealIP` remains, for backward compatibility. Deprecated notes were added to `RealIP`, and the transition to secure `ClientIPFrom*` APIs is recommended. Therefore, instead of simply updating dependencies to v5.3.0, it’s necessary to switch to `ClientIPFrom*` middleware that matches the actual network/reverse proxy configuration.
### Scope of the PoC
This repository only verifies the following:
1. Whether `middleware.RealIP` reflects the attacker-controlled XFF value into `RemoteAddr`.
2. Whether this allows bypassing simple IP-based ACLs.
3. Whether using `ClientIPFromXFF()` in v5.3.0 with appropriate proxy configurations results in rejecting the same input.
No scans of real networks, requests to third-party services, DoS attacks, or persistence operations are performed.
### Recommendations
- Update go-chi/chi to v5.3.0 or later.
- Switch from `middleware.RealIP` to `ClientIPFrom*` middleware that matches the actual infrastructure.
- Ensure that the reverse proxy properly overwrites and removes the forwarding headers sent by clients.
- Avoid using IP addresses as the sole basis for authentication and authorization.
### References
- [CVE-2026-72815](https://vulners.com/cve/CVE-2026-72815)
- [GHSA-3fxj-6jh8-hvhx](https://github.com/go-chi/chi/security/advisories/GHSA-3fxj-6jh8-hvhx)
- [go-chi/chi PR #967: middleware.ClientIP](https://github.com/go-chi/chi/pull/967)
- [go-chi/chi v5.3.0](https://github.com/go-chi/chi/releases/tag/v5.3.0)