Releases: labstack/echo
v4.15.0
Security
WARNING: 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-originornone: 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 validation
Example:
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: #2858
Type-Safe Generic Parameter Binding
-
Added generic functions for type-safe parameter extraction and context access by @aldas in #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:
- Path parameters:
PathParam[T],PathParamOr[T] - Query parameters:
QueryParam[T],QueryParamOr[T],QueryParams[T],QueryParamsOr[T] - Form values:
FormParam[T],FormParamOr[T],FormParams[T],FormParamsOr[T] - Context store:
ContextGet[T],ContextGetOr[T]
Supported Types:
Primitives (bool,string,int/uintvariants,float32/float64),time.Duration,time.Time
(with custom layouts and Unix timestamp support), and custom types implementingBindUnmarshaler,
TextUnmarshaler, orJSONUnmarshaler.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")
- Path parameters:
PR: #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:
- Swaps the response writer using
http.TimeoutHandler - Must be the first middleware in the chain (fragile constraint)
- Can cause races with other middleware (Logger, metrics, custom middleware)
- Has been the source of multiple race condition fixes over the years
What should you use instead?
The ContextTimeout middleware (available since v4.12.0) provides timeout functionality using Go's standard
context mechanism. It is:
- Race-free by design
- Can be placed anywhere in the middleware chain
- Simpler and more maintainable
- Compatible with all other middleware
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.DeadlineExceededshould 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)
})- Background tasks: For long-running background tasks, use goroutines with context:
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")
}
})Full Changelog: v4.14.0...v4.15.0
v4.14.0
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())If you are developing anything more substantial than a demo, use middleware.RequestLoggerWithConfig()
Security
What's Changed
- Update deps by @aldas in #2807
- refactor to use reflect.TypeFor by @cuiweixie in #2812
- Use Go 1.25 in CI by @aldas in #2810
- Modernize context.go by replacing interface{} with any by @vishr in #2822
- Fix typo in SetParamValues comment by @vishr in #2828
- Fix typo in ContextTimeout middleware comment by @vishr in #2827
- Improve BasicAuth middleware: use strings.Cut and RFC compliance by @vishr in #2825
- Fix duplicate plus operator in router backtracking logic by @yuya-morimoto in #2832
- Replace custom private IP range check with built-in net.IP.IsPrivate by @kumapower17 in #2835
- Ensure proxy connection is closed in proxyRaw function(#2837) by @kumapower17 in #2838
- Update deps by @aldas in #2843
- Logger middleware json string escaping and deprecation by @aldas in #2849
- Update golang.org/x/* deps by @aldas in #2850
- Changelog for 4.14.0 by @aldas in #2851
New Contributors
- @cuiweixie made their first contribution in #2812
- @yuya-morimoto made their first contribution in #2832
- @kumapower17 made their first contribution in #2835
Full Changelog: v4.13.4...v4.14.0
v4.13.4
What's Changed
- chore: fix some typos in comment by @zhuhaicity in #2735
- CI: test with Go 1.24 by @aldas in #2748
- Add support for TLS WebSocket proxy by @t-ibayashi-safie in #2762
Security
- Update dependencies for GO-2025-3487, GO-2025-3503 and GO-2025-3595 in #2780
New Contributors
- @zhuhaicity made their first contribution in #2735
- @t-ibayashi-safie made their first contribution in #2762
Full Changelog: v4.13.3...v4.13.4
v4.13.3
v4.13.2 - update dependencies
Security
- Update dependencies (dependabot reports https://pkg.go.dev/vuln/GO-2024-3321 by @aldas in #2721
Full Changelog: v4.13.1...v4.13.2
v4.13.1
JWT Middleware Removed
BREAKING CHANGE: JWT Middleware Removed from Core
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 or see alternative implementation
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
- remove jwt middleware by @stevenwhitehead in #2701
- optimization: struct alignment by @behnambm in #2636
- bind: Maintain backwards compatibility for map[string]interface{} binding by @thesaltree in #2656
- Add Go 1.23 to CI by @aldas in #2675
- improve
MultipartFormtest by @martinyonatann in #2682 bind: add support of multipart multi files by @martinyonatann in #2684- Add TemplateRenderer struct to ease creating renderers for
html/templateandtext/templatepackages. by @aldas in #2690 - Refactor TestBasicAuth to utilize table-driven test format by @ErikOlson in #2688
- Remove broken header by @aldas in #2705
- fix(bind body): content-length can be -1 by @phamvinhdat in #2710
- CORS middleware should compile allowOrigin regexp at creation by @aldas in #2709
- Shorten Github issue template and add test example by @aldas in #2711
New Contributors
- @behnambm made their first contribution in #2636
- @thesaltree made their first contribution in #2656
- @martinyonatann made their first contribution in #2682
- @ErikOlson made their first contribution in #2688
- @phamvinhdat made their first contribution in #2710
- @stevenwhitehead made their first contribution in #2701
Full Changelog: v4.12.0...v4.13.0
v4.12.0
v4.12.0 - 2024-04-15
Security
- Update golang.org/x/net dep because of GO-2024-2687 by @aldas in #2625
Enhancements
- binder: make binding to Map work better with string destinations by @aldas in #2554
- README.md: add Encore as sponsor by @marcuskohlberg in #2579
- Reorder paragraphs in README.md by @aldas in #2581
- CI: upgrade actions/checkout to v4 by @aldas in #2584
- Remove default charset from 'application/json' Content-Type header by @doortts in #2568
- CI: Use Go 1.22 by @aldas in #2588
- binder: allow binding to a nil map by @georgmu in #2574
- Add Skipper Unit Test In BasicBasicAuthConfig and Add More Detail Explanation regarding BasicAuthValidator by @RyoKusnadi in #2461
- fix some typos by @teslaedison in #2603
- fix: some typos by @pomadev in #2596
- Allow ResponseWriters to unwrap writers when flushing/hijacking by @aldas in #2595
- Add SPDX licence comments to files. by @aldas in #2604
- Upgrade deps by @aldas in #2605
- Change type definition blocks to single declarations. This helps copyโฆ by @aldas in #2606
- Fix Real IP logic by @cl-bvl in #2550
- Default binder can use
UnmarshalParams(params []string) errorinterโฆ by @aldas in #2607 - Default binder can bind pointer to slice as struct field. For example
*[]stringby @aldas in #2608 - Remove maxparam dependence from Context by @aldas in #2611
- When route is registered with empty path it is normalized to
/. by @aldas in #2616 - proxy middleware should use httputil.ReverseProxy for SSE requests by @aldas in #2624
New Contributors
- @marcuskohlberg made their first contribution in #2579
- @doortts made their first contribution in #2568
- @georgmu made their first contribution in #2574
- @RyoKusnadi made their first contribution in #2461
- @teslaedison made their first contribution in #2603
- @pomadev made their first contribution in #2596
- @cl-bvl made their first contribution in #2550
Full Changelog: v4.11.4...v4.12.0
v4.11.4 upgrade dependencies
Security
Enhancements
- Update deps and mark Go version to 1.18 as this is what golang.org/x/* use #2563
- Request logger: add example for Slog https://pkg.go.dev/log/slog #2543
v4.11.3
Security
- 'c.Attachment' and 'c.Inline' should escape filename in 'Content-Disposition' header to avoid 'Reflect File Download' vulnerability. #2541
Enhancements