{"id":"CVE-2026-118655","kind":"vulnerability","aliases":["CVE-2026-118655","GHSA-xwq5-6cqp-vx96"],"related":[],"title":"Echo has a Static Middleware Double-Unescape Path Traversal","description":"## Summary\n\nCommit a9ede66a (PR #3006, issue #2599) silently fixed a path traversal vulnerability in the Echo web framework's static file middleware.\n\n## Vulnerability\n\nThe static middleware double-unescaped URL paths. Go's net/http already decodes Request.URL.Path, but middleware/static.go unconditionally called url.PathUnescape() again:\n\n```go\n// BEFORE (vulnerable)\npathUnescape := true\n```\n\nThis reassembled path traversal sequences from double-encoded input. An attacker could send GET /%2e%2e%2fsecret.txt or /..%252fsecret.txt and the double-unescape would produce ../secret.txt.\n\n## Fix\n```go\n// AFTER (fixed)\npathUnescape := false\n```\n\nThe commit's test TestStatic_percentEncodedTraversalIsBlocked explicitly verifies traversal vectors are blocked.\n\n## Impact\nArbitrary file read from server filesystem via percent-encoded path traversal.\n\n## References\n- Fix: https://github.com/labstack/echo/commit/a9ede66a\n- Issue: https://github.com/labstack/echo/issues/2599\n- PR: https://github.com/labstack/echo/pull/3006\n\n## Patches\n\nFixed in `github.com/labstack/echo/v5` v5.2.0 and `github.com/labstack/echo/v4` v4.15.3, where the Static middleware stopped unescaping an already decoded path. Maintainer analysis: reading files outside the configured root could not be reproduced; the confirmed impact was that a double-encoded slash (`%252F`) could reach a file under a guarded route when the Static middleware is registered globally. Upgrade to v5.4.0 / v4.16.0 or later, which also includes related fixes for encoded and dot-segment paths.\n\n## Workarounds\n\nKeep files that need protection outside the Static middleware's root directory.","summary":"Echo's middleware.Static decodes the request path a second time, so double-encoded path separators can be rebuilt before the filesystem lookup. An attacker can reach files under a route that is supposed to be guarded when the static middleware is registered globally.","severity":"medium","cvss":5.9,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"github.com/labstack/echo/v5","fixed":["5.2.0"],"affected":"< 5.2.0","ecosystem":"go"},{"name":"github.com/labstack/echo/v4","fixed":["4.15.3"],"affected":"< 4.15.3","ecosystem":"go"}],"ecosystems":["go"],"tags":["cwe-174","echo","go","package","self-hosted"],"not_affected_if":["no-static-middleware","static-middleware-scoped-to-route"],"how_to_check":"- Check the Echo version in go.mod with `grep labstack/echo go.mod`; versions before `4.15.3` and `5.2.0` are affected.\n- Look for `middleware.Static` registered with `e.Use(...)` at the top level, which applies it to all routes.","fix":"- Upgrade the Go module `github.com/labstack/echo/v4` to `4.15.3` or later.\n- Upgrade `github.com/labstack/echo/v5` to `5.2.0` or later.","status":"open","published_at":"2026-10-28T20:17:22+00:00","first_seen_at":"2026-10-28T20:35:10+00:00","triaged_at":"2026-10-28T20:36:17+00:00","updated_at":"2026-10-28T21:07:44+00:00","category":"package","confidence":0.6,"triage":{"at":"2026-10-28T20:36:17Z","model":"claude-haiku-5-5","output":{"fix":"- Upgrade the Go module `github.com/labstack/echo/v4` to `4.15.3` or later.\n- Upgrade `github.com/labstack/echo/v5` to `5.2.0` or later.","reach":"internet","title":"Echo Go framework: static middleware double-decodes paths, exposing guarded files","impact":"medium","summary":"Echo's middleware.Static decodes the request path a second time, so double-encoded path separators can be rebuilt before the filesystem lookup. An attacker can reach files under a route that is supposed to be guarded when the static middleware is registered globally.","category":"package","nicknames":[],"who_cares":["go","echo","self-hosted"],"confidence":0.6,"needs_auth":"unknown","worst_case":"Attacker reads files under guarded routes on the server","analyst_note":"","how_to_check":"- Check the Echo version in go.mod with `grep labstack/echo go.mod`; versions before `4.15.3` and `5.2.0` are affected.\n- Look for `middleware.Static` registered with `e.Use(...)` at the top level, which applies it to all routes.","needs_analyst":false,"not_affected_if":["no-static-middleware","static-middleware-scoped-to-route"],"who_is_affected":"Applications that serve files with Echo's static middleware and register it globally, so it runs before route-level access checks on other paths. Apps that mount static middleware only on a specific group or that serve no files from disk are unlikely to be exposed. Teams that do not use middleware.Static can skip it.","user_interaction":"no","needs_special_setup":"yes","severity_if_unknown":"medium"},"cost_usd":0.000616,"input_tokens":3320,"output_tokens":567,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-118655':13A,21A '-174':29B '-2026':12A,20A '/labstack/echo/commit/a9ede66a':191C '/labstack/echo/issues/2599':195C '/labstack/echo/pull/3006':199C '/labstack/echo/v4':27A,210C '/labstack/echo/v5':24A,205C '/secret.txt':155C '252f':244C '252fsecret.txt':147C '2599':86C '2e':143C,144C '2fsecret.txt':145C '3006':84C '6cqp':17A 'a9ede66a':82C 'alreadi':114C,219C 'also':267C 'analysi':223C 'arbitrari':175C 'attack':60B,139C 'block':173C 'call':120C 'commit':81C,163C 'configur':228C 'confirm':235C 'could':140C,230C,245C 'cve':11A,19A 'cwe':28B 'decod':39B,115C,220C 'directori':290C 'dot':275C 'dot-seg':274C 'doubl':7A,48B,107C,135C,151C,241C 'double-encod':47B,134C,240C 'double-unescap':6A,106C,150C 'echo':1A,30B,36B,95C 'encod':49B,136C,184C,242C,272C 'explicit':168C 'fals':161C 'file':63B,100C,176C,225C,248C,280C 'filesystem':57B,180C 'fix':88C,156C,159C,188C,201C,270C 'framework':97C 'get':142C 'ghsa':15A 'ghsa-xwq5-6cqp-vx96':14A 'github.com':23A,26A,190C,194C,198C,204C,209C 'github.com/labstack/echo/commit/a9ede66a':189C 'github.com/labstack/echo/issues/2599':193C 'github.com/labstack/echo/pull/3006':197C 'github.com/labstack/echo/v4':25A,208C 'github.com/labstack/echo/v5':22A,203C 'global':79B,259C 'go':31B,111C,123C,157C 'guard':72B,251C 'host':35B 'impact':174C,236C 'includ':268C 'input':137C 'issu':85C,192C 'keep':279C 'later':265C 'lookup':58B 'maintain':222C 'middlewar':5A,76B,101C,105C,215C,256C,287C 'middleware.static':38B 'middleware/static.go':118C 'need':282C 'net/http':113C 'outsid':226C,284C 'packag':32B 'patch':200C 'path':9A,42B,50B,90C,110C,130C,185C,221C,277C 'pathunescap':126C,160C 'percent':183C 'percent-encod':182C 'percentencodedtraversalisblock':167C 'pr':83C,196C 'produc':154C 'protect':283C 'reach':62B,246C 'read':177C,224C 'reassembl':129C 'rebuilt':54B 'refer':187C 'regist':78B,258C 'relat':269C 'reproduc':233C 'request':41B 'request.url.path':116C 'root':229C,289C 'rout':66B,252C 'second':44B 'segment':276C 'self':34B 'self-host':33B 'send':141C 'separ':51B 'sequenc':132C 'server':179C 'silent':87C 'slash':243C 'static':4A,75B,99C,104C,214C,255C,286C 'stop':216C 'summari':80C 'suppos':69B 'test':165C 'teststat':166C 'time':45B 'travers':10A,91C,131C,170C,186C 'true':127C 'uncondit':119C 'unescap':8A,108C,152C,217C 'upgrad':260C 'url':109C 'url.pathunescape':121C 'v4.15.3':211C 'v4.16.0':263C 'v5.2.0':206C 'v5.4.0':262C 'vector':171C 'verifi':169C 'via':181C 'vulner':92C,102C,125C 'vx96':18A 'web':96C 'workaround':278C 'would':153C 'xwq5':16A","nicknames":[],"mitigations":[],"who_affected":"Applications that serve files with Echo's static middleware and register it globally, so it runs before route-level access checks on other paths. Apps that mount static middleware only on a specific group or that serve no files from disk are unlikely to be exposed. Teams that do not use middleware.Static can skip it.","tier":"C","verified":{},"analyst_revisit_at":null,"first_public_at":"2026-10-28T20:17:22+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N","cvss_by":"GitHub","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-118655","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-118655","severity":null,"published_at":"2026-10-28T20:17:22+00:00","modified_at":"2026-10-28T20:17:22+00:00","first_seen_at":"2026-10-28T20:35:10+00:00","fetched_at":"2026-10-28T20:35:10+00:00","note":null},{"source":"ghsa","external_id":"GHSA-xwq5-6cqp-vx96","url":"https://github.com/advisories/GHSA-xwq5-6cqp-vx96","severity":"medium","published_at":"2026-10-28T21:04:39+00:00","modified_at":"2026-10-28T21:04:40+00:00","first_seen_at":"2026-10-28T21:07:44+00:00","fetched_at":"2026-10-28T21:07:44+00:00","note":null}],"documents":[],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}