CVE-2026-118651
Echo: Reverse Proxy Forwards Attacker-Supplied X-Real-IP to Upstream by Default
Echo is a Go web framework. From 4.0.0 until 5.4.0, the Proxy middleware can preserve an attacker-supplied X-Real-IP header and forward it to an upstream service when Echo.IPExtractor is not configured. A remote client can therefore make upstream services receive a spoofed client address, undermining IP-based access controls, rate limiting, audit logging, or geographic restrictions that trust Echo's forwarded identity. This issue is fixed in Echo 5.4.0.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- None
- Integrity
- Low
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
5.3
Echo: Reverse Proxy Forwards Attacker-Supplied X-Real-IP to Upstream by Default
Echo is a Go web framework. From 4.0.0 until 5.4.0, the Proxy middleware can preserve an attacker-supplied X-Real-IP header and forward it to an upstream service when Echo.IPExtractor is not configured. A remote client can therefore make upstream services receive a spoofed client address, undermining IP-based access controls, rate limiting, audit logging, or geographic restrictions that trust Echo's forwarded identity. This issue is fixed in Echo 5.4.0.
- Record
CVE-2026-118651- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N - Weakness
- CWE-346
- Updated
- 2026-11-02
EUVDEUVD-2026-112406
5.3
Echo is a Go web framework. From 4.0.0 until 5.4.0, the Proxy middleware can preserve an attacker-supplied X-Real-IP header and forward it to an upstream service when Echo.IPExtractor is not configured. A remote client can therefore make upstream services receive a spoofed client address, undermining IP-based access controls, rate limiting, audit logging, or geographic restrictions that trust Echo's forwarded identity. This issue is fixed in Echo 5.4.0.
- Record
EUVD-2026-112406- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-99jh-6h7p-pp36
5.3
Echo: Reverse Proxy Forwards Attacker-Supplied X-Real-IP to Upstream by Default
Summary
The Echo proxy middleware (middleware/proxy.go) preserves an incoming X-Real-IP header verbatim and forwards it to the upstream service when Echo#IPExtractor is not configured — which is the default. Because any HTTP client can supply an arbitrary X-Real-IP value, an attacker can cause Echo to relay a spoofed client IP address to every upstream service behind the proxy, undermining upstream IP-based access controls, rate limiting, audit logging, and geo-restriction.
Affected Component
middleware/proxy.go—ProxyConfig.ToMiddleware(), header-rewriting block (lines 351–355)
Description
The header-preservation condition passes spoofed values to upstream
ProxyConfig.ToMiddleware() (proxy.go:338-405) prepares forwarding headers before dispatching each request. The X-Real-IP rewrite logic at lines 351-355 reads:
// proxy.go:351-355
// Basically it's not good practice to unconditionally pass incoming x-real-ip header to upstream.
// However, for backward compatibility, legacy behavior is preserved unless you configure Echo#IPExtractor.
if req.Header.Get(echo.HeaderXRealIP) == "" || c.Echo().IPExtractor != nil {
req.Header.Set(echo.HeaderXRealIP, c.RealIP())
}
The condition is TRUE (and therefore overwrites the header with a derived value) only when:
- The header is absent —
req.Header.Get(echo.HeaderXRealIP) == ""; or IPExtractoris explicitly configured —c.Echo().IPExtractor != nil
The condition is FALSE — and the header is left unchanged — when the request arrives with an X-Real-IP header already set and IPExtractor is nil. Because Echo.New() leaves IPExtractor as nil, this is the out-of-the-box behaviour for every application that uses Proxy() or ProxyWithConfig() without extra configuration.
An attacker who sets X-Real-IP to any value causes Echo to forward exactly that value to the upstream, with no modification or validation.
The comment in the source code confirms intent and the security gap
The inline comment at line 351-352 explicitly states:
"Basically it's not good practice to unconditionally pass incoming x-real-ip header to upstream. However, for backward compatibility, legacy behavior is preserved unless you configure Echo#IPExtractor."
The framework is aware that the default is insecure and retains it for backward compatibility. No warning appears in the Proxy() or ProxyWithConfig() documentation, so operators who follow the standard setup example receive a silently insecure proxy configuration.
This is structurally identical to the documented insecurity in ip.go:27:
"Note: if you don't set
Echo#IPExtractorexplicitly, Echo fallback to legacy behavior, which is not a good choice."
Full execution chain
- Attacker sends
GET /api/adminto the Echo proxy with headerX-Real-IP: 203.0.113.1(a trusted corporate IP) ToMiddleware()evaluates the guard at line 353: header is present (!= ""),IPExtractorisnil→ condition isFALSEreq.Header.Setis not called; the upstream request carries the original, attacker-suppliedX-Real-IP: 203.0.113.1- Upstream service checks
X-Real-IPagainst its IP allowlist → finds203.0.113.1→ grants access - Attacker reaches an endpoint that should be restricted to the corporate IP range
Secondary impact path (audit poisoning):
- All upstream log entries, rate-limit counters, and geo-restriction checks are evaluated against
203.0.113.1rather than the real client IP, rendering audit trails and security analytics unreliable.
Proof of Concept
package main
import (
"fmt"
"log"
"net/http"
echo "github.com/labstack/echo/v5"
"github.com/labstack/echo/v5/middleware"
)
func main() {
// Upstream server: echoes back the X-Real-IP it received
upstream := http.NewServeMux()
upstream.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w,…
- Record
GHSA-99jh-6h7p-pp36- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N - Weakness
- CWE-346
- Updated
- 2026-11-02
NVD
5.3
Echo is a Go web framework. From 4.0.0 until 5.4.0, the Proxy middleware can preserve an attacker-supplied X-Real-IP header and forward it to an upstream service when Echo.IPExtractor is not configured. A remote client can therefore make upstream services receive a spoofed client address, undermining IP-based access controls, rate limiting, audit logging, or geographic restrictions that trust Echo's forwarded identity. This issue is fixed in Echo 5.4.0.
- Record
CVE-2026-118651- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N - Weakness
- CWE-346
- Updated
- 2026-11-02
OSV
5.3
Echo: Reverse Proxy Forwards Attacker-Supplied X-Real-IP to Upstream by Default
Echo is a Go web framework. From 4.0.0 until 5.4.0, the Proxy middleware can preserve an attacker-supplied X-Real-IP header and forward it to an upstream service when Echo.IPExtractor is not configured. A remote client can therefore make upstream services receive a spoofed client address, undermining IP-based access controls, rate limiting, audit logging, or geographic restrictions that trust Echo's forwarded identity. This issue is fixed in Echo 5.4.0.
- Record
CVE-2026-118651- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N - Weakness
- CWE-346
- Updated
- 2026-11-06
OSVDEBIAN-CVE-2026-118651
5.3
Echo is a Go web framework. From 4.0.0 until 5.4.0, the Proxy middleware can preserve an attacker-supplied X-Real-IP header and forward it to an upstream service when Echo.IPExtractor is not configured. A remote client can therefore make upstream services receive a spoofed client address, undermining IP-based access controls, rate limiting, audit logging, or geographic restrictions that trust Echo's forwarded identity. This issue is fixed in Echo 5.4.0.
- Record
DEBIAN-CVE-2026-118651- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N - Updated
- 2026-11-02
OSVGHSA-99jh-6h7p-pp36
5.3
Echo: Reverse Proxy Forwards Attacker-Supplied X-Real-IP to Upstream by Default
Summary
The Echo proxy middleware (middleware/proxy.go) preserves an incoming X-Real-IP header verbatim and forwards it to the upstream service when Echo#IPExtractor is not configured — which is the default. Because any HTTP client can supply an arbitrary X-Real-IP value, an attacker can cause Echo to relay a spoofed client IP address to every upstream service behind the proxy, undermining upstream IP-based access controls, rate limiting, audit logging, and geo-restriction.
Affected Component
middleware/proxy.go—ProxyConfig.ToMiddleware(), header-rewriting block (lines 351–355)
Description
The header-preservation condition passes spoofed values to upstream
ProxyConfig.ToMiddleware() (proxy.go:338-405) prepares forwarding headers before dispatching each request. The X-Real-IP rewrite logic at lines 351-355 reads:
// proxy.go:351-355
// Basically it's not good practice to unconditionally pass incoming x-real-ip header to upstream.
// However, for backward compatibility, legacy behavior is preserved unless you configure Echo#IPExtractor.
if req.Header.Get(echo.HeaderXRealIP) == "" || c.Echo().IPExtractor != nil {
req.Header.Set(echo.HeaderXRealIP, c.RealIP())
}
The condition is TRUE (and therefore overwrites the header with a derived value) only when:
- The header is absent —
req.Header.Get(echo.HeaderXRealIP) == ""; or IPExtractoris explicitly configured —c.Echo().IPExtractor != nil
The condition is FALSE — and the header is left unchanged — when the request arrives with an X-Real-IP header already set and IPExtractor is nil. Because Echo.New() leaves IPExtractor as nil, this is the out-of-the-box behaviour for every application that uses Proxy() or ProxyWithConfig() without extra configuration.
An attacker who sets X-Real-IP to any value causes Echo to forward exactly that value to the upstream, with no modification or validation.
The comment in the source code confirms intent and the security gap
The inline comment at line 351-352 explicitly states:
"Basically it's not good practice to unconditionally pass incoming x-real-ip header to upstream. However, for backward compatibility, legacy behavior is preserved unless you configure Echo#IPExtractor."
The framework is aware that the default is insecure and retains it for backward compatibility. No warning appears in the Proxy() or ProxyWithConfig() documentation, so operators who follow the standard setup example receive a silently insecure proxy configuration.
This is structurally identical to the documented insecurity in ip.go:27:
"Note: if you don't set
Echo#IPExtractorexplicitly, Echo fallback to legacy behavior, which is not a good choice."
Full execution chain
- Attacker sends
GET /api/adminto the Echo proxy with headerX-Real-IP: 203.0.113.1(a trusted corporate IP) ToMiddleware()evaluates the guard at line 353: header is present (!= ""),IPExtractorisnil→ condition isFALSEreq.Header.Setis not called; the upstream request carries the original, attacker-suppliedX-Real-IP: 203.0.113.1- Upstream service checks
X-Real-IPagainst its IP allowlist → finds203.0.113.1→ grants access - Attacker reaches an endpoint that should be restricted to the corporate IP range
Secondary impact path (audit poisoning):
- All upstream log entries, rate-limit counters, and geo-restriction checks are evaluated against
203.0.113.1rather than the real client IP, rendering audit trails and security analytics unreliable.
Proof of Concept
package main
import (
"fmt"
"log"
"net/http"
echo "github.com/labstack/echo/v5"
"github.com/labstack/echo/v5/middleware"
)
func main() {
// Upstream server: echoes back the X-Real-IP it received
upstream := http.NewServeMux()
upstream.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w,…
- Record
GHSA-99jh-6h7p-pp36- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N - Weakness
- CWE-346
- Updated
- 2026-11-06
OSVUBUNTU-CVE-2026-118651
5.3
Echo is a Go web framework. From 4.0.0 until 5.4.0, the Proxy middleware can preserve an attacker-supplied X-Real-IP header and forward it to an upstream service when Echo.IPExtractor is not configured. A remote client can therefore make upstream services receive a spoofed client address, undermining IP-based access controls, rate limiting, audit logging, or geographic restrictions that trust Echo's forwarded identity. This issue is fixed in Echo 5.4.0.
- Record
UBUNTU-CVE-2026-118651- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N - Updated
- 2026-11-05
OSVGO-2026-6875 No score
Reverse Proxy Forwards Attacker-Supplied X-Real-IP to Upstream by Default in github.com/labstack/echo
Reverse Proxy Forwards Attacker-Supplied X-Real-IP to Upstream by Default in github.com/labstack/echo
- Record
GO-2026-6875- Updated
- 2026-11-06
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
github.com/labstack/echo/v5Go |
before 5.4.0 | 5.4.0 |
github.com/labstack/echo/v4Go |
4.0.0 to 4.16.2 | None known |
golang-github-labstack-echoDebian:12 |
All versions, plus listed versions 4.11.1-14.11.1-24.12.0-14.2.1-3 |
None known |
golang-github-labstack-echoDebian:13 |
All versions, plus listed versions 4.12.0-1 |
None known |
golang-github-labstack-echoDebian:14 |
All versions, plus listed versions 4.12.0-1 |
None known |
github.com/labstack/echo/v4Go |
4.0.0 and later | None known |
golang-github-labstack-echo.v2Ubuntu:20.04:LTS |
All versions, plus listed versions 2.2.0-1 |
None known |
golang-github-labstack-echo.v3Ubuntu:20.04:LTS |
All versions, plus listed versions 3.3.5-1 |
None known |
golang-github-labstack-echoUbuntu:22.04:LTS |
All versions, plus listed versions 4.2.1-2 |
None known |
golang-github-labstack-echo.v2Ubuntu:22.04:LTS |
All versions, plus listed versions 2.2.0-2 |
None known |
Show 4 moreShow less
| Package | Affected | Fixed |
|---|---|---|
golang-github-labstack-echo.v3Ubuntu:22.04:LTS |
All versions, plus listed versions 3.3.10-1 |
None known |
golang-github-labstack-echoUbuntu:24.04:LTS |
All versions, plus listed versions 4.11.1-2 |
None known |
golang-github-labstack-echoUbuntu:26.10 |
All versions, plus listed versions 4.12.0-1 |
None known |
golang-github-labstack-echoUbuntu:26.04:LTS |
All versions, plus listed versions 4.12.0-1 |
None known |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected, aliases | OSV | |
| facts | OSV | |
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-118651 is a medium vulnerability (CVSS 5.3) in Labstack Echo, published October 28, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.21%, the 10th percentile. Fixed in github.com/labstack/echo/v5 5.4.0.
References
github.com/labstack/echo/security/advisories/GHSA-99jh-6h7p-pp36
github.com/labstack/echo/commit/fc410094b2f3415cf2bf5204082137b205bfd5af
github.com/labstack/echo/releases/tag/v5.4.0
github.com/advisories/GHSA-99jh-6h7p-pp36
github.com/CVEProject/cvelistV5/tree/main/cves/2026/118xxx/CVE-2026-118651.json
nvd.nist.gov/vuln/detail/CVE-2026-118651
Left out here: the rest of 2 source descriptions. The JSON record has them.