|
1 | 1 | # Changelog |
2 | 2 |
|
| 3 | +## v5.3.0 - 2026-07-12 |
| 4 | + |
| 5 | +**Logic changes** |
| 6 | +PR [#2996](https://github.com/labstack/echo/pull/2996) revert back to `v4` behavior for a group registering implicit 404 handlers. |
| 7 | + |
| 8 | +If you do not want this behavior, can do not want implicit 404 handlers for groups, use: |
| 9 | +```go |
| 10 | +e := echo.NewWithConfig(echo.Config{NoGroupAutoRegister404Routes: true}) |
| 11 | +g := e.Group("/api") |
| 12 | +``` |
| 13 | + |
| 14 | +some other noteworthy echancements: |
| 15 | +* Adds first-class support for the QUERY HTTP method [RFC 10008](https://www.rfc-editor.org/info/rfc10008/) in https://github.com/labstack/echo/pull/3038 |
| 16 | +```go |
| 17 | +e.QUERY("/", func(c *Context) error { |
| 18 | + return c.String(http.StatusTeapot, "OK") |
| 19 | +}) |
| 20 | +``` |
| 21 | + |
| 22 | +* Router: automatically handle HEAD request by GET handlers in https://github.com/labtack/echo/pull/2949 |
| 23 | +```go |
| 24 | +e := echo.NewWithConfig(echo.Config{ |
| 25 | + Router: echo.NewRouter(echo.RouterConfig{ |
| 26 | + AutoHandleHEAD: true, |
| 27 | + }), |
| 28 | +}) |
| 29 | +``` |
| 30 | + |
| 31 | +**Enhancements** |
| 32 | + |
| 33 | +* perf(json): pooled-buffer JSON deserialize by @vishr in https://github.com/labstack/echo/pull/3023 |
| 34 | +* perf(router): cache-friendly static child lookup by @vishr in https://github.com/labstack/echo/pull/3024 |
| 35 | +* update golang.org/x deps to latest versions by @aldas in https://github.com/labstack/echo/pull/3034 |
| 36 | +* pin GitHub Actions to full commit SHAs and rework actions SHAs to own variables by @aldas in https://github.com/labstack/echo/pull/3035 |
| 37 | +* docs(csrf): fix godoc typo in Generator default (tp -> to) by @DucMinhNe in https://github.com/labstack/echo/pull/3026 |
| 38 | +* docs(cors): note reverse-proxy header duplication by @vishr in https://github.com/labstack/echo/pull/3027 |
| 39 | +* feat: add support for HTTP QUERY method by @thdxg in https://github.com/labstack/echo/pull/3038 |
| 40 | +* docs: fix typos in API_CHANGES_V5.md by @maxtaran2010 in https://github.com/labstack/echo/pull/3039 |
| 41 | +* Router: auto HEAD to GET by @aldas in https://github.com/labstack/echo/pull/2949 |
| 42 | +* Revert back to v4 behavior for group registering implicit 404 handler… by @aldas in https://github.com/labstack/echo/pull/2996 |
| 43 | + |
| 44 | + |
| 45 | +## v5.2.1 - 2026-06-15 |
| 46 | + |
| 47 | +**Security** |
| 48 | + |
| 49 | +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. |
| 50 | + |
| 51 | +Given following situation: |
| 52 | +```go |
| 53 | +// 0. |
| 54 | +// given folder structure: |
| 55 | +// private.txt |
| 56 | +// public/ |
| 57 | +// public/index.html |
| 58 | +// public/text.txt |
| 59 | +// public/admin/private.txt |
| 60 | + |
| 61 | +// 1. share `public/` folder contents from the server root. This folder actually contains subfolder `admin` which |
| 62 | +// contents we want to forbid from downloading |
| 63 | +e.Static("/", "public") |
| 64 | + |
| 65 | +// 2. naively assume that everything under /admin folder is now forbidden |
| 66 | +e.GET("/admin/*", func(c *Context) error { |
| 67 | + return ErrForbidden |
| 68 | +}) |
| 69 | +``` |
| 70 | + |
| 71 | +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. |
| 72 | + |
| 73 | +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. |
| 74 | + |
| 75 | +If you want to guard routes - use middlewares on `Static*` methods and before `Static` middleware. |
| 76 | + |
| 77 | + |
| 78 | +------ |
| 79 | + |
| 80 | +* revert PR #3009 changes to just disabling path escaping by default in static methods/middleware by @aldas in https://github.com/labstack/echo/pull/3016 |
| 81 | + |
| 82 | +Closes [GHSA-vfp3-v2gw-7wfq](https://github.com/labstack/echo/security/advisories/GHSA-vfp3-v2gw-7wfq) more completely: the previous fix (#3009) rejected explicitly encoded |
| 83 | +separators at the handler level; this patch makes the no-unescape behavior the **default** so new configurations are safe without extra opt-out steps. |
| 84 | + |
| 85 | +**What changed:** `DisablePathUnescaping` (on `StaticConfig` and `StaticDirectoryHandlerConfig`) is deprecated and replaced by `EnablePathUnescaping` (default `false`). Path unescaping is now opt-in. |
| 86 | + |
| 87 | +**What this protects:** With `EnablePathUnescaping: false` (new default), encoded separators (`%2F`, `%5C`) are never decoded before routing or file lookup, so they cannot |
| 88 | +bypass route-level authentication or other middleware guards. |
| 89 | + |
| 90 | +**What this does NOT protect:** Serving a directory with `Static`, `StaticFS`, or `StaticDirectoryHandler` exposes its **entire subtree**. Sibling routes are not a reliable |
| 91 | +ACL boundary — attach authorization middleware directly to the static mount, or serve sensitive sub-trees under separate guarded routes. |
| 92 | + |
| 93 | +**Breaking change / migration:** If you serve files whose names contain URL-encoded characters (e.g., `/hello%20world.txt` → `hello world.txt`), you must now opt in: |
| 94 | + |
| 95 | + ```go |
| 96 | + // Static middleware |
| 97 | + e.Use(middleware.StaticWithConfig(middleware.StaticConfig{ |
| 98 | + EnablePathUnescaping: true, // only safe when NOT relying on route-based ACL guards |
| 99 | + ... |
| 100 | + })) |
| 101 | + |
| 102 | + // StaticDirectoryHandler |
| 103 | + middleware.StaticDirectoryHandler(fs, &middleware.StaticDirectoryHandlerConfig{ |
| 104 | + EnablePathUnescaping: true, |
| 105 | + }) |
| 106 | +``` |
| 107 | + |
| 108 | + |
3 | 109 | ## v5.2.0 - 2026-06-14 |
4 | 110 |
|
5 | 111 | **Security** |
|
0 commit comments