GHSA-vfp3-v2gw-7wfq

Suggest an improvement
Source
https://github.com/advisories/GHSA-vfp3-v2gw-7wfq
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/08/GHSA-vfp3-v2gw-7wfq/GHSA-vfp3-v2gw-7wfq.json
JSON Data
https://api.test.osv.dev/v1/vulns/GHSA-vfp3-v2gw-7wfq
Aliases
Downstream
CGA (8)
MINI (10)
Published
2026-08-25T16:13:29Z
Modified
2026-08-26T15:25:53Z
Severity
  • 7.5 (High) CVSS_V3 - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N CVSS Calculator
Summary
Echo: Encoded slash (%2F) bypasses route-level protection and exposes static files
Details

Summary

Echo's router and static file handler disagree on URL path decoding. The router matches routes using the raw encoded path (preserving %2F as-is), while StaticDirectoryHandler unescapes %2F to / before resolving filesystem paths. This allows an attacker to bypass route-level access controls and read static files without authorization.

Details

Root cause 1 — router.go lines 798-802: The router uses req.URL.RawPath for route matching when useEscapedPathForRouting is false (the default). This means /admin%2Fsecret.txt is treated as a single path segment and does NOT match the /admin/* route pattern.

if !r.useEscapedPathForRouting && req.URL.RawPath != "" {
    path = req.URL.RawPath
}

Root cause 2 — echo.go lines 559-568: StaticDirectoryHandler calls url.PathUnescape() on the path parameter before opening files. This converts %2F back to /, resolving admin/secret.txt on disk.

if !disablePathUnescaping {
    tmpPath, err := url.PathUnescape(p)
    p = tmpPath
}
name := filepath.ToSlash(filepath.Clean(strings.TrimPrefix(p, "/")))

PoC (Screenshot)

Sample: image

403: image

Bypass with encoded slash: image

Impact

Unauthorized static file disclosure. Applications that protect route prefixes with authentication middleware while also serving static files from a broader root are vulnerable. An attacker only needs to encode the slash (/%2F) in the URL to bypass all route-level protection.

Common affected pattern:

adminGroup := e.Group("/admin", authMiddleware)
e.StaticFS("/", os.DirFS("public"))
Database specific
{
    "cwe_ids":  [
        "CWE-22"
    ],
    "github_reviewed":  true,
    "github_reviewed_at":  "2026-08-25T16:13:29Z",
    "nvd_published_at":  "2026-06-26T17:16:34Z",
    "severity":  "HIGH"
}
References

Affected packages

Go / github.com/labstack/echo/v5

Package

Name
github.com/labstack/echo/v5
View open source insights on deps.dev
Purl
pkg:golang/github.com/labstack/echo/v5

Affected ranges

Type
SEMVER
Events
Introduced
0 Unknown introduced version / All previous versions are affected
Fixed
5.2.0

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/08/GHSA-vfp3-v2gw-7wfq/GHSA-vfp3-v2gw-7wfq.json"

Go / github.com/labstack/echo/v4

Package

Name
github.com/labstack/echo/v4
View open source insights on deps.dev
Purl
pkg:golang/github.com/labstack/echo/v4

Affected ranges

Type
SEMVER
Events
Introduced
0 Unknown introduced version / All previous versions are affected
Fixed
4.15.3

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/08/GHSA-vfp3-v2gw-7wfq/GHSA-vfp3-v2gw-7wfq.json"

Go / github.com/labstack/echo

Package

Name
github.com/labstack/echo
View open source insights on deps.dev
Purl
pkg:golang/github.com/labstack/echo

Affected ranges

Type
SEMVER
Events
Introduced
0 Unknown introduced version / All previous versions are affected
Last Affected
3.3.10

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/08/GHSA-vfp3-v2gw-7wfq/GHSA-vfp3-v2gw-7wfq.json"