NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Go modules · #65 by repository stars
Last release 8 days ago
06 Oct 2026
Release timing varies
gaps range from 8 days to 3 months
Most releases are documented
notes for 37 of 56 stable releases
Nothing withdrawn
no release was ever pulled
8 years old
514 releases · first in 2019
Nothing published for this version
This release fixes several security issues. Upgrading is recommended. Some fixes change behavior; read "Behavior changes to check before upgrading" be
Security
This release fixes several security issues. Upgrading is recommended. Some fixes change behavior; read "Behavior changes to check before upgrading" below.
Context.Scheme() now uses the X-Forwarded-Proto, X-Forwarded-Protocol, X-Forwarded-Ssl and X-Url-Scheme headers only when the request comes directly from a loopback, link-local or private network address or a unix socket. Before this, any client could send X-Forwarded-Proto: https over plain HTTP and skip HTTPSRedirect. When X-Forwarded-Proto is present, only it is used (its last value), and the scheme is returned in lowercase. the new Echo#SchemeExtractor field selects the strategy: ExtractSchemeFromHeaders(...TrustOption) (default), ExtractSchemeDirect() or LegacySchemeExtractor(). The Secure middleware now sets HSTS based on Context.Scheme(). The Proxy middleware always sets X-Forwarded-Proto from Context.Scheme() and removes X-Forwarded-Ssl, X-Forwarded-Protocol and X-Url-Scheme before forwarding. GHSA-2ffq-g2xg-c22pContext.JSONP and Context.JSONPBlob accept only a callback that is empty, a JavaScript identifier or a dot-separated path of identifiers (ASCII letters, digits, _ and $). Any other callback returns a 400 Bad Request error that wraps the new ErrInvalidJSONPCallback, and nothing is written. JSONP responses now carry X-Content-Type-Options: nosniff. JSONP lets any website read the response with the user's cookies, so do not use it for data that needs authentication. GHSA-h9g5-28mm-hx3gGET, HEAD, OPTIONS, TRACE or CONNECT. Before this, with the MethodFromForm or MethodFromQuery getter and MethodOverride registered with Use before the CSRF middleware, _method=GET skipped the CSRF check. Register MethodOverride with Echo#Pre. GHSA-r7w9-592q-9vg4/%09/evil.example/ redirected browsers to evil.example. GHSA-v753-g4cw-jm48/admin%2Fsecret.txt or /%61dmin/secret.txt can no longer reach a file under a guarded /admin/* route. GHSA-375p-5qhx-8wq4 The Static middleware and StaticDirectoryHandler (used by Echo.Static, Echo.StaticFS, Group.Static and Group.StaticFS) no longer serve paths with a ., .. or empty segment, such as /assets/../admin/secret.txt, also after path unescaping. GHSA-3pmx-cf9f-34xrgolang.org/x/text to v0.40.0 (GO-2026-5970).Client IP address (no code change in v4)
Without Echo#IPExtractor, Context.RealIP() in v4 trusts the X-Forwarded-For and X-Real-IP headers from any client, so the rate limiter can be bypassed and the Proxy middleware forwards a spoofed X-Real-IP (GHSA-246p-cpwv-v3jq, GHSA-99jh-6h7p-pp36). Changing this default in v4 would put all clients behind a proxy into one rate-limit bucket, so v4 keeps it. Set an extractor that matches your deployment:
e.IPExtractor = echo.ExtractIPDirect() // no proxy in front of the app
e.IPExtractor = echo.ExtractIPFromXFFHeader() // behind proxies in private networks that set X-Forwarded-For
// behind a proxy with public addresses (e.g. a CDN), also trust its ranges:
// e.IPExtractor = echo.ExtractIPFromXFFHeader(echo.TrustIPRange(cdnRange))v5 uses the direct peer address by default since v5.1.0.
Behavior changes to check before upgrading
100.64.0.0/10) address, its X-Forwarded-Proto is now ignored: HTTPSRedirect redirects in a loop and the Secure middleware stops sending HSTS. This affects, for example, Cloudflare, CloudFront and Azure Front Door connecting to a public origin, the GCP external HTTP(S) load balancer including GKE Ingress (35.191.0.0/16, 130.211.0.0/22), and networks that use 100.64.0.0/10 (such as Alibaba Cloud SLB or EKS custom networking). Trust the proxy's address ranges:
_, gclb1, _ := net.ParseCIDR("35.191.0.0/16")
_, gclb2, _ := net.ParseCIDR("130.211.0.0/22")
e.SchemeExtractor = echo.ExtractSchemeFromHeaders(echo.TrustIPRange(gclb1), echo.TrustIPRange(gclb2))echo.LegacySchemeExtractor() restores the old behavior but is not safe unless every request passes through a proxy that sets these headers. Serverless adapters or middleware that set RemoteAddr to the client's address also make X-Forwarded-Proto ignored (or, if they take it from a header, spoofable).X-Forwarded-Proto. A proxy on a trusted address that passes the client's X-Forwarded-Proto through (for example nginx without proxy_set_header X-Forwarded-Proto $scheme;) still lets the client choose the scheme. An invalid X-Forwarded-Proto value now results in http instead of falling back to the other scheme headers.httptest.NewRequest sets RemoteAddr to 192.0.2.1:1234, which is not trusted, so tests that set X-Forwarded-Proto now see http. Set req.RemoteAddr = "10.0.0.1:1234" or use e.SchemeExtractor = echo.LegacySchemeExtractor() in such tests.X-Forwarded-Ssl, X-Forwarded-Protocol and X-Url-Scheme are no longer forwarded to the upstream; X-Forwarded-Proto carries the scheme.GET (for example with X-HTTP-Method-Override: GET to send a long query in a POST body) is no longer done; such requests keep the POST method./assets//app.js) now return 404; in HTML5 mode the index is still served. The Static middleware no longer finds file names that the client sends with non-default escaping (for example %2C, %40 or lowercase hex like %c3%a9) unless StaticConfig.EnablePathUnescaping is set; Echo.Static has behaved this way since v4.15.4. With StaticConfig.EnablePathUnescaping or Echo#EnablePathUnescapingStaticFiles, encoded dots (%2e%2e) no longer traverse directories, but encoded slashes are still decoded, so do not combine these options with route-based access control.Context.JSONP returns an error for callbacks that are not JavaScript identifiers.Documentation
Echo#Use it runs before route and group middleware, so route guards do not protect the files it serves.If your company depends on Echo, please consider sponsoring it.
One column per quarter.
Nothing published for this version
Breaking change / migration: If you serve files whose names contain URL-encoded characters (e.g., /hello%20world.txt → hello world.txt ), you must now…
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:
// 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.txt → hello world.txt), you must now opt in:
e := echo.New()
e.EnablePathUnescapingStaticFiles = true // <-- enable old behavior
e.Static("/", "public")for static middleware
e.Use(middleware.StaticWithConfig(middleware.StaticConfig{
EnablePathUnescaping: true, // <-- enable old behavior
}))Full Changelog: v4.15.3...v4.15.4
fix(static): reject encoded path separators that bypass route-level middleware by @vishr in #3011
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 (#3009, released in v5.2.0). Thanks to @a-tt-om and @oran-gugu for reporting.
Full Changelog: v4.15.2...v4.15.3
v4.15.3 - Static encoded-separator route bypass fix (GHSA-vfp3-v2gw-7wfq)
Compare
Nothing published for this version
Context.Scheme() should validate values taken from header by @aldas in #2962
v4.15.2 - Context.Scheme() header validation
Compare
Security
Context.Scheme() should validate values taken from header by @aldas in https://github.com/labstack/echo/pull/2962Thanks to @shblue21 for reporting this issue.
CSRF: support older token-based CSRF protection handler that want to render token into template by @aldas in #2905
Full Changelog: v4.15.0...v4.15.1
DEPRECATION NOTICE Timeout Middleware Deprecated - Use ContextTimeout Instead
Security
NB: If your application relies on cross-origin or same-site (same subdomain) requests do not blindly push this version to production
The CSRF middleware now supports the Sec-Fetch-Site header as a modern, defense-in-depth approach to CSRF protection, implementing the OWASP-recommended Fetch Metadata API alongside the traditional token-based mechanism.
How it works:
Modern browsers automatically send the Sec-Fetch-Site header with all requests, indicating the relationship
between the request origin and the target. The middleware uses this to make security decisions:
same-origin or none: Requests are allowed (exact origin match or direct user navigation)same-site: Falls back to token validation (e.g., subdomain to main domain)cross-site: Blocked by default with 403 error for unsafe methods (POST, PUT, DELETE, PATCH)For browsers that don't send this header (older browsers), the middleware seamlessly falls back to traditional token-based CSRF protection.
New Configuration Options:
TrustedOrigins []string: Allowlist specific origins for cross-site requests (useful for OAuth callbacks, webhooks)AllowSecFetchSiteFunc func(echo.Context) (bool, error): Custom logic for same-site/cross-site request validationExample:
e.Use(middleware.CSRFWithConfig(middleware.CSRFConfig{
// Allow OAuth callbacks from trusted provider
TrustedOrigins: []string{"https://oauth-provider.com"},
// Custom validation for same-site requests
AllowSecFetchSiteFunc: func(c echo.Context) (bool, error) {
// Your custom authorization logic here
return validateCustomAuth(c), nil
// return true, err // blocks request with error
// return true, nil // allows CSRF request through
// return false, nil // falls back to legacy token logic
},
}))
PR: https://github.com/labstack/echo/pull/2858
Type-Safe Generic Parameter Binding
Added generic functions for type-safe parameter extraction and context access by @aldas in https://github.com/labstack/echo/pull/2856
Echo now provides generic functions for extracting path, query, and form parameters with automatic type conversion, eliminating manual string parsing and type assertions.
New Functions:
PathParam[T], PathParamOr[T]QueryParam[T], QueryParamOr[T], QueryParams[T], QueryParamsOr[T]FormParam[T], FormParamOr[T], FormParams[T], FormParamsOr[T]ContextGet[T], ContextGetOr[T]Supported Types:
Primitives (bool, string, int/uint variants, float32/float64), time.Duration, time.Time
(with custom layouts and Unix timestamp support), and custom types implementing BindUnmarshaler,
TextUnmarshaler, or JSONUnmarshaler.
Example:
// Before: Manual parsing
idStr := c.Param("id")
id, err := strconv.Atoi(idStr)
// After: Type-safe with automatic parsing
id, err := echo.PathParam[int](c, "id")
// With default values
page, err := echo.QueryParamOr[int](c, "page", 1)
limit, err := echo.QueryParamOr[int](c, "limit", 20)
// Type-safe context access (no more panics from type assertions)
user, err := echo.ContextGet[*User](c, "user")
PR: https://github.com/labstack/echo/pull/2856
DEPRECATION NOTICE Timeout Middleware Deprecated - Use ContextTimeout Instead
The middleware.Timeout middleware has been deprecated due to fundamental architectural issues that cause
data races. Use middleware.ContextTimeout or middleware.ContextTimeoutWithConfig instead.
Why is this being deprecated?
The Timeout middleware manipulates response writers across goroutine boundaries, which causes data races that cannot be reliably fixed without a complete architectural redesign. The middleware:
http.TimeoutHandlerWhat should you use instead?
The ContextTimeout middleware (available since v4.12.0) provides timeout functionality using Go's standard
context mechanism. It is:
Migration Guide:
// Before (deprecated):
e.Use(middleware.Timeout())
// After (recommended):
e.Use(middleware.ContextTimeout(30 * time.Second))
Important Behavioral Differences:
Handler cooperation required: With ContextTimeout, your handlers must check context.Done() for cooperative
cancellation. The old Timeout middleware would send a 503 response regardless of handler cooperation, but had
data race issues.
Error handling: ContextTimeout returns errors through the standard error handling flow. Handlers that receive
context.DeadlineExceeded should handle it appropriately:
e.GET("/long-task", func(c echo.Context) error {
ctx := c.Request().Context()
// Example: database query with context
result, err := db.QueryContext(ctx, "SELECT * FROM large_table")
if err != nil {
if errors.Is(err, context.DeadlineExceeded) {
// Handle timeout
return echo.NewHTTPError(http.StatusServiceUnavailable, "Request timeout")
}
return err
}
return c.JSON(http.StatusOK, result)
})
e.GET("/async-task", func(c echo.Context) error {
ctx := c.Request().Context()
resultCh := make(chan Result, 1)
errCh := make(chan error, 1)
go func() {
result, err := performLongTask(ctx)
if err != nil {
errCh <- err
return
}
resultCh <- result
}()
select {
case result := <-resultCh:
return c.JSON(http.StatusOK, result)
case err := <-errCh:
return err
case <-ctx.Done():
return echo.NewHTTPError(http.StatusServiceUnavailable, "Request timeout")
}
})
Enhancements
Nothing published for this version
Nothing published for this version
middleware.Logger has been deprecated. For request logging, use middleware.RequestLogger or middleware.RequestLoggerWithConfig.
middleware.Logger has been deprecated. For request logging, use middleware.RequestLogger or
middleware.RequestLoggerWithConfig.
middleware.RequestLogger replaces middleware.Logger, offering comparable configuration while relying on the
Go standard library’s new slog logger.
The previous default output format was JSON. The new default follows the standard slog logger settings.
To continue emitting request logs in JSON, configure slog accordingly:
slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, nil)))
e.Use(middleware.RequestLogger())
Security
Enhancements
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
chore: fix some typos in comment by @zhuhaicity in https://github.com/labstack/echo/pull/2735
Enhancements
Security
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Update golang.org/x/net dependency GO-2024-3333 in https://github.com/labstack/echo/pull/2722
Security
Update dependencies (dependabot reports GO-2024-3321) in https://github.com/labstack/echo/pull/2721
Security
Fix BindBody ignoring Transfer-Encoding: chunked requests by @178inaba in https://github.com/labstack/echo/pull/2717
Fixes
Transfer-Encoding: chunked requests by @178inaba in https://github.com/labstack/echo/pull/2717The JWT middleware has been removed from Echo core due to another security vulnerability, CVE-2024-51744. For more details, refer to issue #2699. A dr…
BREAKING CHANGE JWT Middleware Removed from Core use labstack/echo-jwt instead
The JWT middleware has been removed from Echo core due to another security vulnerability, CVE-2024-51744. For more details, refer to issue #2699. A drop-in replacement is available in the labstack/echo-jwt repository.
Important: Direct assignments like token := c.Get("user").(*jwt.Token) will now cause a panic due to an invalid cast. Update your code accordingly. Replace the current imports from "github.com/golang-jwt/jwt" in your handlers to the new middleware version using "github.com/golang-jwt/jwt/v5".
Background:
The version of golang-jwt/jwt (v3.2.2) previously used in Echo core has been in an unmaintained state for some time. This is not the first vulnerability affecting this library; earlier issues were addressed in PR #1946.
JWT middleware was marked as deprecated in Echo core as of v4.10.0 on 2022-12-27. If you did not notice that, consider leveraging tools like Staticcheck to catch such deprecations earlier in you dev/CI flow. For bonus points - check out gosec.
We sincerely apologize for any inconvenience caused by this change. While we strive to maintain backward compatibility within Echo core, recurring security issues with third-party dependencies have forced this decision.
Enhancements
MultipartForm test by @martinyonatann in https://github.com/labstack/echo/pull/2682bind : add support of multipart multi files by @martinyonatann in https://github.com/labstack/echo/pull/2684html/template and text/template packages. by @aldas in https://github.com/labstack/echo/pull/2690Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Update golang.org/x/net dep because of GO-2024-2687 by @aldas in https://github.com/labstack/echo/pull/2625
Security
Enhancements
UnmarshalParams(params []string) error inter… by @aldas in https://github.com/labstack/echo/pull/2607*[]string by @aldas in https://github.com/labstack/echo/pull/2608/. by @aldas in https://github.com/labstack/echo/pull/2616Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Upgrade golang.org/x/crypto to v0.17.0 to fix vulnerability issue #2562
Your coding agent can read these notes before it upgrades. Set up the MCP server →