Repository navigation
Releases
v5.4.6
Security
- Proxy middleware: a client could remove
X-Forwarded-Protofrom the upstream request by naming it in theConnectionheader, on plain HTTP requests and WebSocket upgrades. The proxy now setsX-Forwarded-Protoagain after Go removes hop-by-hop headers, as it already does forX-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
Security
- Proxy middleware: a client could remove
X-Forwarded-Protofrom the upstream request by naming it in theConnectionheader, on plain HTTP requests and WebSocket upgrades. The proxy now setsX-Forwarded-Protoagain after Go removes hop-by-hop headers, as it already does forX-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
Security
- Redirect middleware:
HTTPSRedirect,HTTPSWWWRedirect,HTTPSNonWWWRedirect,WWWRedirectandNonWWWRedirectnow return400 Bad Requestinstead of redirecting when the host is empty, starts with:or., contains%, or is empty after removingwww.. Before this change, such hosts could produce an open redirect. The middleware no longer redirectsOPTIONS *requests, mapswsandwsstohttpandhttpsin redirect targets, and matches thewww.prefix case-insensitively. Fixes GHSA-3f6j-cw5h-qw9c (#3217) in #3220.
Fixes
- Trailing slash middleware:
AddTrailingSlashandRemoveTrailingSlashkeep escaped path segments such as%2Fin redirect and forward targets, so the request still matches its original route. Fixes #3206 in #3221. - IPv6 zones:
ExtractIPFromXFFHeaderandExtractIPFromRealIPHeadertrust zoned link-local proxy peers such as[fe80::1%eth0]:8080, with or without a port. Fixes #3179 in #3222. - Header binding:
BindHeadersno 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
Security
- Redirect middleware:
HTTPSRedirect,HTTPSWWWRedirect,HTTPSNonWWWRedirect,WWWRedirectandNonWWWRedirectnow return400 Bad Requestinstead of redirecting when the host is empty, starts with:or., contains%, or is empty after removingwww.. Before this change, such hosts could produce an open redirect. The middleware no longer redirectsOPTIONS *requests, mapswsandwsstohttpandhttpsin redirect targets, and matches thewww.prefix case-insensitively. Fixes GHSA-3f6j-cw5h-qw9c (#3217) in #3224.
Fixes
- Trailing slash middleware:
AddTrailingSlashandRemoveTrailingSlashkeep escaped path segments such as%2Fin redirect and forward targets, so the request still matches its original route. Fixes #3206 in #3225. - IPv6 zones:
ExtractIPFromXFFHeaderandExtractIPFromRealIPHeadertrust zoned link-local proxy peers such as[fe80::1%eth0]:8080, with or without a port. Fixes #3179 in #3226. - Header binding:
BindHeadersno longer panics on nil or empty header value slices. Fixes #3169 in #3227.
Behavior changes
Context.RealIP()andExtractIPDirect()now return a zoned link-local peer without its zone:fe80::1, notfe80::1%eth0. Update logs, allowlists or rate-limit keys that store the zoned form.HTTPSWWWRedirectkeeps its v4 behavior: it does not redirect plain HTTP requests for hosts that already start withwww.. v5 redirects these requests.
No public API, dependency or minimum Go-version changes; Go 1.26 or later remains required.
v5.4.4
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
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
UnescapePathParamValuesis enabled, preserving literal percent-containing values. - Correct
UseEscapedPathForMatchingdocumentation 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
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-IPfromContext.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 whenIPExtractoris 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
Fixes
- Require a space after the case-insensitive
Basicauthentication scheme. Malformed schemes such asBasicXno longer reach credential validation or consumeAllowedCheckLimit. 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.2Go 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
Fixes
- Require a space after the case-insensitive
Basicauthentication scheme. Malformed schemes such asBasicXno 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.TokenLookupconfigurations 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.2Go 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
Security fixes
Upgrade with go get github.com/labstack/echo/v5@v5.4.1.
- Validate the sending peer before accepting
X-Real-IPinExtractIPFromRealIPHeader, 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