Skip to content

Releases

v5.4.6

Choose a tag to compare

@vishr vishr released this 15 Nov 05:17
Immutable release. Only release title and notes can be modified.
f275a6b

Security

  • Proxy middleware: a client could remove X-Forwarded-Proto from the upstream request by naming it in the Connection header, on plain HTTP requests and WebSocket upgrades. The proxy now sets X-Forwarded-Proto again after Go removes hop-by-hop headers, as it already does for X-Real-IP. Fixes GHSA-h6x5-phvw-c55c. Reported by zachary-satterly.

Behavior change

A custom balancer that replaces the request and sets its own X-Forwarded-Proto no longer reaches the upstream with that value; the proxy uses the scheme of the original request. A custom ProxyConfig.Transport can still set the header.

No public API, dependency or minimum Go-version changes.

v4.16.5

Choose a tag to compare

@vishr vishr released this 15 Nov 05:17
Immutable release. Only release title and notes can be modified.
1a99655

Security

  • Proxy middleware: a client could remove X-Forwarded-Proto from the upstream request by naming it in the Connection header, on plain HTTP requests and WebSocket upgrades. The proxy now sets X-Forwarded-Proto again after Go removes hop-by-hop headers, as it already does for X-Real-IP. Fixes GHSA-h6x5-phvw-c55c. Reported by zachary-satterly.

Behavior change

A custom balancer that replaces the request and sets its own X-Forwarded-Proto no longer reaches the upstream with that value; the proxy uses the scheme of the original request. A custom ProxyConfig.Transport can still set the header.

No public API, dependency or minimum Go-version changes; Go 1.26 or later remains required.

v5.4.5

Choose a tag to compare

@vishr vishr released this 12 Nov 09:14
Immutable release. Only release title and notes can be modified.
53cdb2b

Security

  • Redirect middleware: HTTPSRedirect, HTTPSWWWRedirect, HTTPSNonWWWRedirect, WWWRedirect and NonWWWRedirect now return 400 Bad Request instead of redirecting when the host is empty, starts with : or ., contains %, or is empty after removing www.. Before this change, such hosts could produce an open redirect. The middleware no longer redirects OPTIONS * requests, maps ws and wss to http and https in redirect targets, and matches the www. prefix case-insensitively. Fixes GHSA-3f6j-cw5h-qw9c (#3217) in #3220.

Fixes

  • Trailing slash middleware: AddTrailingSlash and RemoveTrailingSlash keep escaped path segments such as %2F in redirect and forward targets, so the request still matches its original route. Fixes #3206 in #3221.
  • IPv6 zones: ExtractIPFromXFFHeader and ExtractIPFromRealIPHeader trust zoned link-local proxy peers such as [fe80::1%eth0]:8080, with or without a port. Fixes #3179 in #3222.
  • Header binding: BindHeaders no longer panics on nil or empty header value slices. Fixes #3169 in #3223.

Behavior change

Context.RealIP() and ExtractIPDirect() now return a zoned link-local peer without its zone: fe80::1, not fe80::1%eth0. Update logs, allowlists or rate-limit keys that store the zoned form.

No public API, dependency or minimum Go-version changes.

v4.16.4

Choose a tag to compare

@vishr vishr released this 12 Nov 09:14
Immutable release. Only release title and notes can be modified.
25c7b04

Security

  • Redirect middleware: HTTPSRedirect, HTTPSWWWRedirect, HTTPSNonWWWRedirect, WWWRedirect and NonWWWRedirect now return 400 Bad Request instead of redirecting when the host is empty, starts with : or ., contains %, or is empty after removing www.. Before this change, such hosts could produce an open redirect. The middleware no longer redirects OPTIONS * requests, maps ws and wss to http and https in redirect targets, and matches the www. prefix case-insensitively. Fixes GHSA-3f6j-cw5h-qw9c (#3217) in #3224.

Fixes

  • Trailing slash middleware: AddTrailingSlash and RemoveTrailingSlash keep escaped path segments such as %2F in redirect and forward targets, so the request still matches its original route. Fixes #3206 in #3225.
  • IPv6 zones: ExtractIPFromXFFHeader and ExtractIPFromRealIPHeader trust zoned link-local proxy peers such as [fe80::1%eth0]:8080, with or without a port. Fixes #3179 in #3226.
  • Header binding: BindHeaders no longer panics on nil or empty header value slices. Fixes #3169 in #3227.

Behavior changes

  • Context.RealIP() and ExtractIPDirect() now return a zoned link-local peer without its zone: fe80::1, not fe80::1%eth0. Update logs, allowlists or rate-limit keys that store the zoned form.
  • HTTPSWWWRedirect keeps its v4 behavior: it does not redirect plain HTTP requests for hosts that already start with www.. v5 redirects these requests.

No public API, dependency or minimum Go-version changes; Go 1.26 or later remains required.

v5.4.4

Choose a tag to compare

@vishr vishr released this 30 Oct 04:46
Immutable release. Only release title and notes can be modified.
a45c7bb

Proxy identity hardening

The proxy now retains its derived X-Real-IP header when an incoming request includes Connection: X-Real-IP, including mixed-case and duplicate Connection values. The value is restored after Go removes hop-by-hop headers, before the upstream transport runs.

The same captured identity is preserved across retries and balancer request replacement, and the protection applies to WebSocket upgrades. Default and custom transports and extractors remain supported.

Released v5.4.3 can omit the identity header for those requests. Identity spoofing additionally depends on an upstream that falls back to an untrusted source when the header is absent. This release does not change v5’s direct-peer default or the affected ranges of the earlier default-IP CVEs.

No new client-IP migration is required for v5. Applications behind proxies should continue using an extractor that trusts their own proxies. No public API, dependency, or minimum Go-version changes.

Validation

The implementation passed fresh independent Claude review, full race tests on Go 1.25 and 1.27, vet, staticcheck, golint, and govulncheck. Permanent tests cover HTTP/default/custom transports, raw WebSocket negotiation, duplicate/mixed-case header nominations, and a stateful extractor across request-swapping retries.

Implementation: #3200. This ports the additional proxy identity protection released in v4.16.3.

Full Changelog: v5.4.3...v5.4.4

v5.4.3

Choose a tag to compare

@vishr vishr released this 30 Oct 03:27
Immutable release. Only release title and notes can be modified.
6e06e88

Security

Upgrade to v5.4.3 to fix a static route-guard bypass involving encoded empty path segments in non-default path-matching or unescaping configurations. The confirmed impact is access to protected files inside a static root. The fix validates raw and decoded request paths and wildcard boundaries, including singly and doubly encoded leading slashes and guarded directory indexes.

Advisory: GHSA-v97q-3xf5-rj74

Fixes

  • Decode path parameters only once when UnescapePathParamValues is enabled, preserving literal percent-containing values.
  • Correct UseEscapedPathForMatching documentation without changing its behavior.
  • Preserve correctly escaped filenames and static prefixes such as /assets*.

Thanks to MyWorld319 for the static bypass report and alexreid for the parameter-decoding report.

Documentation

  • Publish v4 support dates and the Echo Support offer (#3193).
  • Mention Echo Pro in the Sponsors section (#3192).

Full Changelog: v5.4.2...v5.4.3

v4.16.3

Choose a tag to compare

@vishr vishr released this 30 Oct 04:31
Immutable release. Only release title and notes can be modified.
c99c7cb

Security and migration

Applications behind proxies must configure Echo#IPExtractor to trust their own proxies before upgrading. Without an extractor, clients behind one proxy share its address for rate limiting, IP-based access controls, logging, and proxy forwarding. The safe default now ignores client-supplied IP headers.

This release fixes the remaining v4 exposure for:

  • CVE-2026-118651: Proxy always derives upstream X-Real-IP from Context.RealIP(), including after hop-by-hop header stripping and on WebSocket upgrades. One derived identity is preserved across retries.
  • CVE-2026-118653: Context.RealIP() uses the connection peer when IPExtractor is unset, so rotating spoofed forwarded-IP headers cannot create fresh default rate-limit buckets.

Use echo.ExtractIPDirect() without a proxy. Behind a proxy, use ExtractIPFromXFFHeader or ExtractIPFromRealIPHeader with trust restricted to your proxies. Configure the outermost proxy to replace client-supplied identity headers. Explicit extractors and custom rate-limit identifiers retain their behavior.

Migration example with explicit proxy trust ranges

Other changes

  • Resolve bare IPv4 and IPv6 connection addresses without a port.
  • Document v4 support dates (#3194).

No dependency or minimum Go-version changes; Go 1.26 or later remains required.

The security fix (#3197) passed independent agent and Claude reviews, full race tests on Go 1.26 and 1.27, and GitHub Linux/macOS/Windows checks.

Full Changelog: v4.16.2...v4.16.3

v5.4.2

Choose a tag to compare

@vishr vishr released this 23 Oct 01:54
Immutable release. Only release title and notes can be modified.
7c312e0

Fixes

  • Require a space after the case-insensitive Basic authentication scheme. Malformed schemes such as BasicX no longer reach credential validation or consume AllowedCheckLimit. Valid credentials are still required. #3138, thanks to @Shubham-Padkonde.
  • Reject empty cookie tokens and empty client tokens in CSRF validation. This is defense in depth; it does not introduce a new security advisory. #3135, thanks to @hoangtaiki.

Upgrade

go get github.com/labstack/echo/v5@v5.4.2

Go 1.25 remains the module minimum. Build deployments with a supported, patched Go toolchain. No dependencies or public APIs changed in this release.

The security fixes released in v5.4.1 are included unchanged. Their first patched version remains v5.4.1.

Validation: the fixes passed regression tests and upstream race-test and lint checks on Linux, macOS and Windows with Go 1.25, 1.26 and 1.27. The new regressions were also verified to fail without the fixes.

Full changelog: v5.4.1...v5.4.2

v4.16.2

Choose a tag to compare

@vishr vishr released this 23 Oct 01:54
Immutable release. Only release title and notes can be modified.
679c415

Fixes

  • Require a space after the case-insensitive Basic authentication scheme. Malformed schemes such as BasicX no longer invoke the credential validator. Valid credentials are still required. This adapts the v5 correction to v4's single-header API. #3188, backport of #3138, with credit to @Shubham-Padkonde.
  • Reject empty cookie tokens and empty client tokens in CSRF validation. This is defense in depth; it does not introduce a new security advisory. #3189, backport of #3135, with credit to @hoangtaiki.
  • Reject CSRFConfig.TokenLookup configurations that produce no recognized token extractors. Middleware creation now returns an error instead of silently skipping token validation. #3149, thanks to @orinnz; backport of the existing v5 validation in #3067.

Upgrade

go get github.com/labstack/echo/v4@v4.16.2

Go 1.26 remains the module minimum. Build deployments with a supported, patched Go toolchain. No dependencies or public APIs changed in this release. Applications with invalid CSRF token lookup configuration will now fail middleware creation at startup.

The security fixes, bounded BodyDump and Decompress defaults, and dependency updates released in v4.16.1 are included unchanged. Their first patched version remains v4.16.1.

Validation: the fixes passed regression tests and upstream race-test, lint and benchmark checks on Linux, macOS and Windows with Go 1.26 and 1.27. The new regressions were also verified to fail without the fixes; local race tests and vet passed.

Full changelog: v4.16.1...v4.16.2

v5.4.1

Choose a tag to compare

@vishr vishr released this 22 Oct 16:32
Immutable release. Only release title and notes can be modified.
a6a9673

Security fixes

Upgrade with go get github.com/labstack/echo/v5@v5.4.1.

  • Validate the sending peer before accepting X-Real-IP in ExtractIPFromRealIPHeader, preventing client IP spoofing when that extractor is configured. GHSA-h53f-rm2w-w7rg
  • Validate upstream WebSocket upgrade responses through Go's HTTP reverse proxy. Rejected upgrades no longer leave a raw tunnel that bypasses Echo routing and route middleware. GHSA-cxf3-9h37-7rr8
  • Close both WebSocket connections when either side disconnects, including when an upstream ignores client EOF. GHSA-9969-6676-49h5
  • Preserve the complete request body beyond the BodyDump capture limit and propagate read errors, including BodyLimit overflows. GHSA-x9ff-22gv-65f4, #3105
  • Restore the original response writer before returning BodyDump buffers to the pool, preventing writes into a reused buffer during error handling. #3174
  • Accept decompressed bodies exactly at the configured limit; keep overflow errors sticky. #3136
  • Include the BodyLimit overflow-check correction and static-path hardening already merged since v5.4.0.

Behavior to review when upgrading

The proxy removes incoming Forwarded headers as defensive hardening. Backends relying on that header should use forwarding headers generated from the configured trusted IP extractor and scheme. WebSocket requests now honor the configured proxy transport, response modifier, target path and query in the same way as HTTP requests; ws and wss targets remain supported.

BodyDump capture limits bound logging only: handlers receive the full request, and clients receive the full response. Applications must still consume request bodies and handle read errors to enforce streaming body limits.

Go 1.25 remains the module minimum. Build deployments with a supported, patched Go toolchain.

Other changes

This release also includes ValidateCtx, router fixes for escaped colons, custom methods and parameter storage, binding support for OpenAPI date formats, and documentation updates.

Thanks to @rm-Umar, @Duodum, @irisitymichaelgrundberg, @Hama1cco, @jakezwang, @Shubham-Padkonde and @rajpreetcodes for reports and contributions, and to the contributors credited in the individual commits.

Validation: upstream lint checks and race tests passed on Linux, macOS and Windows with Go 1.25, 1.26 and 1.27. Local tests on patched toolchains, vet, staticcheck and govulncheck also passed; govulncheck reported no reachable vulnerabilities.

Full changelog: v5.4.0...v5.4.1