Download Latest Version v5.3.1 source code.zip (555.2 kB)
Email in envelope

Get an email when there's a new version of Echo

Home / v4.15.4
Name Modified Size InfoDownloads / Week
Parent folder
README.md 2026-06-15 2.4 kB
v4.15.4 source code.tar.gz 2026-06-15 434.5 kB
v4.15.4 source code.zip 2026-06-15 486.5 kB
Totals: 3 Items   923.4 kB 0

Security

Fixes GHSA-vfp3-v2gw-7wfq: an encoded path separator (%2F or %5C) in a static file URL could bypass route-level middleware (e.g. authentication on a sibling route) and disclose static files. Both StaticDirectoryHandler (used by Static/StaticFS) and the Static middleware are affected. Backport of the v5 fix (#3016, released in v5.2.1). Thanks to @a-tt-om and @oran-gugu for reporting.


Make serving static file releated methods and middleware not unescape path by default - so how the way Router interprets paths and Static methods/middleware is consistent.

Given following situation:

:::go
// 0.
// given folder structure:
// private.txt
// public/
// public/index.html
// public/text.txt
// public/admin/private.txt

// 1. share `public/` folder contents from the server root. This folder actually contains subfolder `admin` which
// contents we want to forbid from downloading
e.Static("/", "public")

// 2. naively assume that everything under /admin folder is now forbidden
e.GET("/admin/*", func(c *Context) error {
    return ErrForbidden
})

Then requests to /admin%2fprivate.txt would not be matched to GET /admin/* route (routing does not look unescaped path) and static file serving will use unescaped path to serve the file.

Note: this way of "guarding" subfolders will never work for for paths like /assets/../admin%2fprivate.txt which will path.Clean("/assets/../admin%2fprivate.txt") to /admin/private.txt and are servable if static file serving is configured to unescape paths.

If you want to guard routes - use middlewares on Static* methods and before Static middleware.

Breaking change / migration: If you serve files whose names contain URL-encoded characters (e.g., /hello%20world.txthello world.txt), you must now opt in:

:::go
    e := echo.New()
    e.EnablePathUnescapingStaticFiles = true  // <-- enable old behavior
    e.Static("/", "public")

for static middleware

:::go
    e.Use(middleware.StaticWithConfig(middleware.StaticConfig{
        EnablePathUnescaping: true, // <-- enable old behavior
    }))

Full Changelog: https://github.com/labstack/echo/compare/v4.15.3...v4.15.4

Source: README.md, updated 2026-06-15