chi's RealIP Middleware allows IP spoofing via unvalidated X-Forwarded-For headerGHSA-rjr7-jggh-pgcp
GHSA-rjr7-jggh-pgcp is a CWE-290 vulnerability in github.com/go-chi/chi/middleware. A fix is available for github.com/go-chi/chi/middleware — see the affected versions and patch details below.
Exploitation Status
Proof-of-concept exploit code exists
- CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
- CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.
Exploitation and automatability from CISA’s SSVC triage for GHSA-rjr7-jggh-pgcp.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
Real-World Exposure
github.com/go-chi/chi/middleware🐹github.com/go-chi/chi/v2/middleware🐹github.com/go-chi/chi/v3/middleware🐹github.com/go-chi/chi/v4/middleware🐹github.com/go-chi/chi/v5/middlewareReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.
Description
Summary
realip middleware in go-chi/chi trusts headers like x-forwarded-for without checking them, so attackers can fake their ip and bypass rate limits or access controls
Details
the vuln is in middleware/realip.go , the realIP() function pulls IPs straight from client headers and replaces r.RemoteAddr without checking if the request came from a trusted proxy
func realIP(r *http.Request) string {
var ip string
if tcip := r.Header.Get(trueClientIP); tcip != "" {
ip = tcip // controlled by attacker
} else if xrip := r.Header.Get(xRealIP); xrip != "" {
ip = xrip // controlled by attacker
} else if xff := r.Header.Get(xForwardedFor); xff != "" {
ip, _, _ = strings.Cut(xff, ",") // controlled by attacker
}
// ...
return ip
}
no trusted proxy cidr check in place, any client can send these headers
PoC
create a server with chi and use realip middleware
package main
import (
"fmt"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
func main() {
r := chi.NewRouter()
r.Use(middleware.RealIP)
r.Get("/admin", func(w http.ResponseWriter, r *http.Request) {
// ip-based access control got bypassed
if r.RemoteAddr == "127.0.0.1" {
w.Write([]byte("SECRET ADMIN DATA"))
return
}
http.Error(w, "Forbidden", 403)
})
http.ListenAndServe(":8080", r)
}
spoofed the ip to bypass access control
curl -H "X-Forwarded-For: 127.0.0.1" http://localhost:8080/admin
Impact
- ip-based access control bypass lets attackers reach restricted endpoints
- rate limiting bypass lets attackers avoid limits by rotating spoofed ips
- audit logs show fake ips picked by attacker instead of real ones
- attackers can get around geo ip restrictions
Remediation Recommendation
validate proxy cidr first before trusting forwarded ip headers
// add your reverse proxy ip addresses here
var trustedProxies = []net.IPNet{
{IP: net.ParseIP("10.0.0.0"), Mask: net.CIDRMask(8, 32)},
{IP: net.ParseIP("172.16.0.0"), Mask: net.CIDRMask(12, 32)},
{IP: net.ParseIP("192.168.0.0"), Mask: net.CIDRMask(16, 32)},
}
func isTrustedProxy(ip net.IP) bool {
for _, cidr := range trustedProxies {
if cidr.Contains(ip) {
return true
}
}
return false
}
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐹Go | github.com/go-chi/chi/middleware | all versions | No fix |
| 🐹Go | github.com/go-chi/chi/v2/middleware | all versions | No fix |
| 🐹Go | github.com/go-chi/chi/v3/middleware | all versions | No fix |
| 🐹Go | github.com/go-chi/chi/v4/middleware | all versions | No fix |
| 🐹Go | github.com/go-chi/chi/v5/middleware | all versions | 5.3.0go get github.com/go-chi/chi/v5/middleware@v5.3.0 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/go-chi/chi/middleware, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
No patched version of github.com/go-chi/chi/middleware has shipped for GHSA-rjr7-jggh-pgcp yet. Where your build allows, override or pin the dependency away from the vulnerable range, and apply any maintainer-recommended mitigation.
Workarounds
Put an independent control in front of the weakness: restrict the affected endpoint or interface to trusted networks, require an additional authentication factor or proxy-level check, and invalidate existing sessions and credentials in case the flaw has already been used.
Fixing This On Your OS
If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.
An IP spoofing flaw exists in go-chi/chi's RealIP middleware (middleware/realip.go). The realIP() function parses untrusted HTTP headers (True-Client-IP, X-Real-IP, X-Forwarded-For) and overwrites r.RemoteAddr without validating upstream proxy identity. Remote unauthenticated attackers can supply arbitrary IP values…
Do not use the `chi/middleware.RealIP` middleware when receiving traffic directly from untrusted networks or unverified proxies. Instead, strip or sanitize client-supplied forwarding headers at an upstream edge proxy or reverse proxy (such as NGINX or HAProxy) before requests reach the application.Source: Red Hat security advisory for GHSA-rjr7-jggh-pgcp (CC BY 4.0)
| Product | Fixed in | Advisory |
|---|---|---|
| Red Hat Hardened Images | spire1-14-main-1.14.7-0.4.hum1 | RHSA-2026:49718 |
| Red Hat Hardened Images | spire1-15-main-1.15.2-0.4.hum1 | RHSA-2026:49732 |
| Red Hat Hardened Images | cosign-main-3.1.3-0.1.hum1 | RHSA-2026:54420 |
Frequently Asked Questions
Is GHSA-rjr7-jggh-pgcp in your dependencies?
Find it across Go, including transitive dependencies.