Security
This release fixes several security issues. Upgrading is recommended. Some fixes change behavior; read "Behavior changes to check before upgrading" below.
- Request scheme:
Context.Scheme()now uses theX-Forwarded-Proto,X-Forwarded-Protocol,X-Forwarded-SslandX-Url-Schemeheaders only when the request comes directly from a loopback, link-local or private network address or a unix socket. Before this, any client could sendX-Forwarded-Proto: httpsover plain HTTP and skipHTTPSRedirect. WhenX-Forwarded-Protois present, only it is used (its last value), and the scheme is returned in lowercase.Echo#SchemeExtractor(andConfig.SchemeExtractor) selects the strategy:ExtractSchemeFromHeaders(...TrustOption)(default),ExtractSchemeDirect()orLegacySchemeExtractor(). The Secure middleware now sets HSTS based onContext.Scheme(). The Proxy middleware always setsX-Forwarded-ProtofromContext.Scheme()and removesX-Forwarded-Ssl,X-Forwarded-ProtocolandX-Url-Schemebefore forwarding. GHSA-2ffq-g2xg-c22p - Proxy middleware: always sets
X-Real-IPfromContext.RealIP(), so a client can no longer pass a spoofedX-Real-IPto the upstream. GHSA-99jh-6h7p-pp36 - JSONP:
Context.JSONPandContext.JSONPBlobaccept 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 newErrInvalidJSONPCallback, and nothing is written. JSONP responses now carryX-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-hx3g - MethodOverride: a POST can no longer be overridden to
GET,HEAD,OPTIONS,TRACEorCONNECT. Before this, with theMethodFromFormorMethodFromQuerygetter and MethodOverride registered withUsebefore the CSRF middleware,_method=GETskipped the CSRF check. Register MethodOverride withEcho#Pre. GHSA-r7w9-592q-9vg4 - Redirects: the trailing slash middlewares and the static directory redirect percent-encode control characters in the redirect path. Before this,
/%09/evil.example/redirected browsers toevil.example. GHSA-v753-g4cw-jm48 - Static files: with the default settings, the Static middleware resolves files from the same form of the path that the router matched, so
/admin%2Fsecret.txtor/%61dmin/secret.txtcan no longer reach a file under a guarded/admin/*route. GHSA-375p-5qhx-8wq4 The Static middleware andStaticDirectoryHandler(used byEcho.Static,Echo.StaticFS,Group.StaticandGroup.StaticFS) no longer serve paths with a.,..or empty segment, such as/assets/../admin/secret.txt, also after path unescaping. GHSA-3pmx-cf9f-34xr
Behavior changes to check before upgrading
- Proxies or load balancers with public IP addresses. If a proxy connects to your app from a public (or
100.64.0.0/10) address, itsX-Forwarded-Protois now ignored:HTTPSRedirectredirects 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 use100.64.0.0/10(such as Alibaba Cloud SLB or EKS custom networking). Trust the proxy's address ranges:Proxies on the same host, in a private network (AWS ALB, in-cluster ingress controllers such as ingress-nginx or Traefik, most PaaS routers) or on a unix socket keep working without changes._, 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 setRemoteAddrto the client's address also makeX-Forwarded-Protoignored (or, if they take it from a header, spoofable). - Trusted proxies must set
X-Forwarded-Proto. A proxy on a trusted address that passes the client'sX-Forwarded-Protothrough (for example nginx withoutproxy_set_header X-Forwarded-Proto $scheme;) still lets the client choose the scheme. An invalidX-Forwarded-Protovalue now results inhttpinstead of falling back to the other scheme headers. - Your own tests.
httptest.NewRequestsetsRemoteAddrto192.0.2.1:1234, which is not trusted, so tests that setX-Forwarded-Protonow seehttp. Setreq.RemoteAddr = "10.0.0.1:1234"or usee.SchemeExtractor = echo.LegacySchemeExtractor()in such tests. - Proxy middleware headers.
X-Real-IPsent to the upstream is now alwaysContext.RealIP(). In a chain like nginx → Echo Proxy → upstream, configureEcho#IPExtractor(for exampleecho.ExtractIPFromRealIPHeader()) to pass the client address on.X-Forwarded-Ssl,X-Forwarded-ProtocolandX-Url-Schemeare no longer forwarded;X-Forwarded-Protocarries the scheme. - MethodOverride. Overriding a POST to
GET(for example withX-HTTP-Method-Override: GETto send a long query in a POST body) is no longer done; such requests keep the POST method. - Static files. Paths with a double slash or dot segment (for example
/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,%40or lowercase hex like%c3%a9) unlessStaticConfig.EnablePathUnescapingis set;Echo.Statichas behaved this way since v5.2.1. WithStaticConfig.EnablePathUnescapingorConfig.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. - JSONP.
Context.JSONPreturns an error for callbacks that are not JavaScript identifiers.
Documentation
IPExtractordocs: corrected the description of the default (the direct peer address has been used since v5.1.0).- Static middleware: when registered with
Echo#Useit runs before route and group middleware, so route guards do not protect the files it serves.