Skip to main content

Labstack Echo CVE-2026-118650

| EUVDEUVD-2026-112404 HIGH
Improper Handling of URL Encoding (Hex Encoding) (CWE-177)
2026-10-28 https://github.com/labstack/echo GHSA-375p-5qhx-8wq4
7.5
CVSS 3.1 · Vendor: https://github.com/labstack/echo
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Identify app serving a directory via global middleware.Static with a route-guarded path
  2. Exploit
    Send %2F-encoded request (e.g. /admin%2Fsecret.txt) with path-as-is
  3. Execution
    Router matches raw path and skips the route/group guard
  4. Impact
    Static handler decodes %2F and serves the protected file

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A05:2025 - Injection
ASVS 5.0
V1 - Encoding and Sanitization URL encoding handling
Exploitation Conditions

Exploitable only when the application (1) mounts middleware.Static globally via e.Use(middleware.Static(...)) so there is no wildcard route and the handler reads the net/http-decoded c.Request().URL.Path, (2) serves a directory publicly, (3) places a sensitive file inside that same static root, and (4) relies on a route- or group-level middleware guard (e.g. e.Group("/admin", ...)) rather than keeping the file outside the root. The default configuration is affected (the EnablePathUnescaping docstring's promise of protection is inaccurate for the global mount). Limiting factors: no file outside the static root is ever reachable; apps using the patched e.StaticFS/StaticDirectoryHandler path (fixed in CVE-2026-55677) are not affected; affected versions are echo/v5 5.0.0-<5.4.0 and echo/v4 <4.16.0; and the whole scenario depends on a configuration the maintainers consider arguably a misconfiguration, so apps that keep protected files outside the static root are not exposed.

Impact

The input CVSS of 7.5 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N) frames this as a network-reachable, low-complexity, unauthenticated confidentiality issue, and the attack mechanics support AV:N/AC:L/PR:N/UI:N: a single %2F-encoded GET bypasses a route/group guard with no credentials or user interaction. However, the C:H rating overstates real-world impact because the advisory is explicit that no file outside the static root is reached - the exposed file already lives in a directory the operator deliberately serves to the public, and impact only materializes under a specific misconfiguration (sensitive file inside a globally-mounted static root, protected only by a route-level guard). The vuln.today decision label is 'this_week' and a vendor patch is available, but no EPSS score and no KEV listing were provided in the input, and there is no evidence of active exploitation. A working proof-of-concept (curl + Go reproduction) is published in the GHSA advisory itself, so exploitation is trivial where the preconditions exist, but the maintainers themselves note the combination 'is arguably a misconfiguration' and may treat it as a documentation fix. Net: this is a real, easy-to-trigger authorization-inconsistency bug warranting prompt patching per the 'this_week' signal, but its practical blast radius is far narrower than the 7.5/C:H base score suggests - it is closer to a medium-risk, configuration-dependent issue than a widespread critical exposure.

Exploit ScenarioDerived

An unauthenticated remote attacker sends GET /admin%2Fsecret.txt with --path-as-is against an app that mounts middleware.Static globally and guards /admin only via route/group middleware; the router matches on the still-encoded path so the guard is skipped, while net/http has already decoded %2F to / so the static handler opens and serves admin/secret.txt (HTTP 200) instead of the 401 the literal path returns. A working proof-of-concept (a minimal Go app plus the two curl commands) is published in the vendor GHSA advisory. Exploitation is low-complexity but only yields files already inside the publicly-served static root.

This Week Schedule remediation this week. Why: HIGH severity (CVSS 7.0-8.9).
Patch available

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Oct 28, 2026

Labstack Echo's global Static middleware serves files whose paths were percent-encoded to dodge route- or group-level middleware guards: when middleware.Static is mounted with e.Use(...) and an application protects a path such as /admin with a group middleware, a request for /admin%2Fsecret.txt skips the guard because the router matches on the raw, still-encoded path, yet the handler opens and returns the same file because it reads the already-decoded c.Request().URL.Path. Echo v5 releases from 5.0.0 before 5.4.0 and v4 releases before 4.16.0 are affected; the advisory ships a reproduction PoC against v5.3.1 (literal path returns 401, %2F form returns the file) and there is no CISA KEV entry or confirmed active exploitation. Impact is bounded to files already inside the served static root - nothing outside the root is reachable - so this is an authorization-consistency flaw exploitable only by deployments that both publish a directory statically and rely on a route guard, rather than keeping sensitive files out of that root.

RemediationAI

Vendor-released patch: upgrade github.com/labstack/echo/v5 to v5.4.0 or github.com/labstack/echo/v4 to v4.16.0 (release notes at https://github.com/labstack/echo/releases/tag/v5.4.0 and https://github.com/labstack/echo/releases/tag/v4.16.0; fix commits b838391e2eade87ae7e5a09d7bb5087bec271ec1 and fc410094b2f3415cf2bf5204082137b205bfd5af). After upgrading, the Static middleware resolves files from the same form of the path the router matched, so /admin%2Fsecret.txt and /%61dmin/secret.txt no longer reach a file under a guarded route, and paths containing ., .. or empty segments are refused. Because middleware registered with Echo#Use runs before route and group middleware, route guards can never protect files served by a global Static middleware - the vendor's stated workaround is to keep protected files outside the Static middleware's root directory, or to serve them with Echo#Static (route-level) behind the guard. Operators should validate behavior changes before rolling out: paths with double slashes or dot segments (e.g. /assets//app.js) now return 404, and filenames sent with non-default escaping are no longer located unless StaticConfig.EnablePathUnescaping is set, which decodes encoded slashes and therefore should not be combined with route-based access control. Audit logs for %2F or otherwise percent-encoded requests to paths beneath a static root are a useful detection signal for prior abuse.

Affected VersionsENISA

Echo 5.0.0, < 5.4.0
Echo < 4.16.0

Affected Packages

go github.com/labstack/echo/v4 fix: 4.16.0
go github.com/labstack/echo/v5 fix: 5.4.0
euvd echo fix: 4.16.0, 5.4.0

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 3 packages in go, euvd

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

Echo is a Go HTTP web framework built on net/http. The router performs route matching against the raw, still-percent-encoded request path, while net/http populates c.Request().URL.Path in decoded form (%2F becomes /). When middleware.Static is registered globally via Echo#Use there is no wildcard route, so middleware/static.go (~L219) falls back to c.Request().URL.Path, cleans it with path.Clean (~L235) and opens the result with currentFS.Open (~L259) - meaning the router and the static handler interpret the same request differently. This is the CWE-177 / CWE-436 interpretation conflict that was already addressed for StaticFS/StaticDirectoryHandler in CVE-2026-55677 (GHSA-vfp3-v2gw-7wfq, patched in 5.2.0) but was left uncovered for the middleware.Static code path; it is distinct from CVE-2026-25766 (GHSA-pgvm-wxw2-hrv9, patched 5.0.3), which concerned Windows backslash traversal outside the root. The misclassification produces CWE-863 incorrect authorization: the access-control expectation set by a route/group guard is inconsistent between the literal and encoded forms of the same URL. The StaticConfig.EnablePathUnescaping docstring additionally claimed the default prevents this bypass, which is inaccurate for the global-mount case, and Echo#Use middleware always runs before route and group middleware, so a route guard structurally cannot protect files a globally mounted Static middleware serves. The v4.16.0 release also notes that under EnablePathUnescaping encoded dots no longer traverse directories but encoded slashes are still decoded, so that option should not be combined with route-based access control.

Know when Go gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

Vendor (https://github.com/labstack/echo) PRIMARY 7.5 HIGH
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
vuln.today AI 5.3 MEDIUM

Unauthenticated remote single-request bypass keeps AV:N/AC:L/PR:N/UI:N, but disclosure is limited to one file already inside an intentionally-public static root, so C:L (not C:H), I:N, A:N.

3.1 AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
4.0 AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N

Primary rating from Vendor (https://github.com/labstack/echo).

CVSS VectorVendor: https://github.com/labstack/echo

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
None
Availability
None

DescriptionCVE.org

Summary

When middleware.Static is mounted globally (e.Use(middleware.Static(...))) and an application relies on a route- or group-level middleware guard to restrict a path that also falls under the served static root, a %2F-encoded request bypasses that guard while the file is still served. This is the same encoding/decoding mismatch fixed for StaticFS/StaticDirectoryHandler in CVE-2026-55677 / GHSA-vfp3-v2gw-7wfq, but the fix did not cover the middleware.Static path. In addition, the StaticConfig.EnablePathUnescaping docstring states the default configuration prevents exactly this bypass, which is inaccurate for the global-mount case.

This is not path traversal: no file outside the static root is accessed. The served file lives inside the static root; the issue is that access-control expectations set by a route guard are inconsistent between the literal and %2F-encoded forms of the same path.

Details

Root cause - the router and the static handler disagree on how to interpret %2F:

  • The router matches routes on the raw, still-encoded path, so GET /admin%2Fsecret.txt does not match a /admin/... route or group; any middleware attached to that route/group is therefore skipped.
  • middleware.Static selects its path source in middleware/static.go (~L219): with a global e.Use mount there is no wildcard route, so it uses c.Request().URL.Path, which net/http has already decoded (%2F → /). It then path.Cleans (~L235) and Opens (~L259) admin/secret.txt, serving the file.

Net effect: for the literal path the guard runs; for the %2F-encoded path the guard is skipped but the same file is served.

Relevant code:

  • middleware/static.go ~L219 (p := c.Request().URL.Path), ~L235 (path.Clean), ~L259 (currentFS.Open)
  • StaticConfig.EnablePathUnescaping docstring (static.go ~L60-67) - claims the default prevents the /admin%2fprivate.txt → /admin/* guard bypass; this is not true for the global mount.

Relationship to prior advisories:

  • CVE-2026-55677 / GHSA-vfp3-v2gw-7wfq (patched 5.2.0): same %2F router-vs-handler mismatch, but fixed for StaticFS/StaticDirectoryHandler. The middleware.Static path was not covered - this report is that gap.
  • CVE-2026-25766 / GHSA-pgvm-wxw2-hrv9 (patched 5.0.3): a *different* issue (Windows backslash traversal outside the root). Referenced only to disambiguate; not the same as this report.

PoC

Environment: golang:1.25, module using the official release (go get github.com/labstack/echo/v5@v5.3.1, no local replace). Static root public/ contains a marker file public/admin/secret.txt = SECRET.

Minimal app (the pattern under test: static served globally + a group guard intended to protect /admin):

go
package main

import (
	"net/http"

	"github.com/labstack/echo/v5"
	"github.com/labstack/echo/v5/middleware"
)

func main() {
	e := echo.New()
	e.Use(middleware.Static("public")) // serves ./public globally (default filesystem)

	admin := e.Group("/admin", func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c *echo.Context) error { return c.String(http.StatusUnauthorized, "auth required") }
	})
	admin.GET("/secret.txt", func(c *echo.Context) error { return c.String(http.StatusOK, "handler") })

	e.Start(":1323")
}

Requests (unauthenticated):

# Literal: route matches -> group guard runs
curl -i http://localhost:1323/admin/secret.txt
# => 401
# %2F-encoded: route does NOT match -> guard skipped, but middleware.Static serves the file
curl -i --path-as-is http://localhost:1323/admin%2Fsecret.txt
# => 200, body: SECRET

Observed on v5.3.1: literal → 401; %2F → 200 with the file contents. For contrast, serving via the (patched) e.StaticFS("/") returns 404 for the same %2F request, showing the middleware.Static path was not covered by the CVE-2026-55677 fix.

Impact

An unauthenticated remote user can retrieve a file served by middleware.Static even when the application attached a route/group middleware guard to that path, by substituting / with %2F. The consequence is limited to files already inside the served static root (CWE-863 authorization inconsistency; CWE-436 interpretation conflict) - there is no access to files outside the static root.

Honest caveat on validity / severity: this only has security impact for applications that (a) serve a directory statically to the public *and* (b) place a sensitive file inside that same directory while relying on a *route-level* guard to protect it. That combination is arguably a misconfiguration - a statically-served directory is public by design - so maintainers may reasonably classify this as a documentation fix (correct the EnablePathUnescaping claim) or won't-fix rather than a code vulnerability. It is filed primarily because (1) the router-vs-handler %2F inconsistency is the exact class fixed in CVE-2026-55677 but left uncovered for middleware.Static, and (2) the docstring currently promises protection it does not provide.

Patches

Fixed in github.com/labstack/echo/v5 v5.4.0 and github.com/labstack/echo/v4 v4.16.0. With the default settings, the Static middleware resolves files from the same form of the path that the router matched, so percent-encoded paths such as /admin%2Fsecret.txt or /%61dmin/secret.txt no longer reach a file under a guarded route. Paths with ., .. or empty segments are no longer served.

Note: middleware registered with Echo#Use runs before route and group middleware, so route guards never protect files served by a global Static middleware. Keep protected files outside its root directory, or serve them with Echo#Static behind the guard.

Workarounds

Keep files that need protection outside the Static middleware's root directory.

Technical POC Analysis

Bug class: improper handling of URL encoding (CWE-177) producing an incorrect authorization decision (CWE-863) through two disagreeing interpretations of the same request path (CWE-436), as classifie…

Full technical POC analysis - root cause, step-by-step exploitation and patch breakdown - is part of the Pro and Business plans.

Executive ViewAI

Why It Matters

CVE-2026-118650 is a high-severity authorization bypass in the Labstack Echo web framework (v4 before 4.16.0 and v5 before 5.4.0) that allows an attacker to retrieve files from protected static directories by encoding the path with %2F, sidestepping any route- or group-level access controls. Organizations running internet-facing Go applications built on affected Echo versions that both serve a static directory and protect paths with middleware-based guards are exposed to unauthorized disclosure of files within that served root. Leadership should care because any sensitive content placed in a protected static directory could be read without authentication, undermining access-control guarantees customers and auditors expect.

Business Impact: High
Compensating Controls

Vendor-released patch: Echo v5.4.0 and v4.16.0. If immediate upgrade is not possible, remove sensitive files from statically served directories, front exposed static paths with reverse-proxy or WAF rules that reject or normalize encoded path separators (%2F), and add a decoded-path authorization check inside the static handler.

Threat Intelligence Overview

Prevalence
Medium
popular Go web framework, but vulnerable pattern needs specific static+guard misconfiguration
Threat Intel
1
1 source
Exploit
POC
Public exploit code exists
Data Quality
4 sources
Confidence: Medium

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity HIGH
CISA KEV No
Public POC Yes
EPSS N/A
Patch available Yes
Active threat No
Deciding rule
HIGH severity (CVSS 7.0-8.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Scheduled
Exploitation· derived
Poc
System Exposure· derived
Open
Automatable· derived
Yes
Human Impact
High

Priority Score

58
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +38
PoC: +20
Weaponized: 0
Threat intel: 0
Gov advisory: 0

More in Go

View all
CVE-2023-44487 HIGH POC
7.5 Oct 10

Denial of service against HTTP/2 server implementations allows remote unauthenticated attackers to exhaust server resour

CVE-2016-5386 HIGH
8.1 Jul 19

The net/http package in Go through 1.6 does not attempt to address RFC 3875 section 4.1.18 namespace conflicts and there

CVE-2025-68121 CRITICAL POC
10.0 Feb 05

Critical certificate validation bypass in Go crypto/tls during session resumption. If ClientCAs or RootCAs fields are mu

CVE-2019-14809 CRITICAL POC
9.8 Aug 13

net/url in Go before 1.11.13 and 1.12.x before 1.12.8 mishandles malformed hosts in URLs, leading to an authorization by

CVE-2026-90942 CRITICAL POC
9.3 Sep 14

Casdoor through 4.4.0 exposes its instance-wide built-in JWT signing private key unmasked through the /api/get-certs and

CVE-2026-101090 CRITICAL POC
9.3 Sep 27

Host header injection in Nezha 2.2.3's OAuth2 redirect endpoint (/api/v1/oauth2/{provider}) allows an unauthenticated re

CVE-2026-78428 HIGH POC
8.8 Sep 17

Session cross-wiring in SUSE NeuVector before 5.6.1 allows an unauthenticated remote attacker to obtain another user's a

CVE-2026-92791 HIGH POC
8.7 Sep 16

Unauthenticated path traversal in Uber Kraken through 0.1.29 allows remote attackers to read files outside the configure

CVE-2018-7187 HIGH POC
8.8 Feb 16

The "go get" implementation in Go 1.9.4, when the -insecure command-line option is used, does not validate the import pa

CVE-2026-16651 HIGH POC
8.7 Sep 21

Denial of service in Temporal Server allows an authenticated caller holding at least namespace read permission to crash

CVE-2026-82405 HIGH POC
8.7 Sep 23

Account takeover in Klever-Go's KleverUpdateAccountPermission built-in (all versions prior to 1.7.20) allows an attacker

CVE-2026-82409 HIGH POC
8.4 Sep 23

Maliciously crafted on-chain account names processed by Klever-Go prior to 1.7.20 are spliced into Elasticsearch _bulk r

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy