{"id":"CVE-2026-118658","kind":"vulnerability","aliases":["CVE-2026-118658","GHSA-23wf-92cp-8pcj"],"related":[],"title":"Echo has Arbitrary Scheme Injection in WWWRedirect/NonWWWRedirect Middlewares via X-Forwarded-Proto","description":"## Summary\n\nThe `c.Scheme()` method in Echo (`context.go:162-181`) trusts the `X-Forwarded-Proto`, `X-Forwarded-Protocol`, and `X-Url-Scheme` request headers without validating that the value is `http` or `https`. The `WWWRedirect()` and `NonWWWRedirect()` middlewares use this unsanitized scheme to construct redirect URLs, allowing an attacker to inject arbitrary URI schemes into the `Location` response header.\n\n## Affected Components\n\n- `context.go:162-181` - `Scheme()` method returns attacker-controlled value verbatim\n- `middleware/redirect.go:172-184` - `redirectWWW`/`redirectNonWWW` use unsanitized scheme\n\n## Proof of Concept\n\n```\nGET /path HTTP/1.1\nHost: example.com\nX-Forwarded-Proto: javascript\n\nResponse:\nHTTP/1.1 301 Moved Permanently\nLocation: javascript://www.example.com/path\n```\n\nConfirmed injectable schemes: `javascript`, `data`, `vbscript`, `file`, `ftp`, `ssh`, `telnet`, `gopher`.\n\nOnly `WWWRedirect()` and `NonWWWRedirect()` (and `WithConfig` variants) are affected. `HTTPSRedirect`, `HTTPSWWWRedirect`, `HTTPSNonWWWRedirect` are NOT affected (they hardcode `https://`).\n\n## Impact\n\n- Open redirect to arbitrary scheme URLs when app is not behind a proxy that strips `X-Forwarded-Proto`\n- Cache poisoning when behind a CDN that caches redirect responses keyed by path\n- `file://` scheme injection could trigger file access in some browser configurations\n\n## Suggested Fix\n\nWhitelist scheme in `c.Scheme()` to only return `http` or `https`:\n\n```go\nfunc (c *Context) Scheme() string {\n    if c.IsTLS() {\n        return \"https\"\n    }\n    if scheme := c.request.Header.Get(HeaderXForwardedProto); scheme != \"\" {\n        scheme = strings.ToLower(strings.TrimSpace(scheme))\n        if scheme == \"https\" {\n            return \"https\"\n        }\n    }\n    return \"http\"\n}\n```\n\n## Disclosure\n\nSource code review, manually verified with actual HTTP server. Tested on Echo v5.0.4 (latest master).\n\n## Patches\n\nFixed in `github.com/labstack/echo/v5` v5.1.1 and `github.com/labstack/echo/v4` v4.15.2. `Context.Scheme()` now accepts only `http`, `https`, `ws` or `wss` from the `X-Forwarded-Proto`, `X-Forwarded-Protocol` and `X-Url-Scheme` headers, and falls back to `http` for any other value (#2953).\n\n## Workarounds\n\nUpgrade to a patched version. If you cannot upgrade, have your edge proxy overwrite or remove the `X-Forwarded-Proto`, `X-Forwarded-Protocol` and `X-Url-Scheme` request headers.","summary":"Echo's WWWRedirect and NonWWWRedirect middlewares build the Location header from the X-Forwarded-Proto request header without validating it. An attacker can make the server return a redirect to a javascript, data, file or similar scheme URL, enabling open redirects and possible cache poisoning behind a CDN.","severity":"medium","cvss":4.7,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"github.com/labstack/echo/v5","fixed":["5.1.1"],"affected":"< 5.1.1","ecosystem":"go"},{"name":"github.com/labstack/echo/v4","fixed":["4.15.2"],"affected":"< 4.15.2","ecosystem":"go"}],"ecosystems":["go"],"tags":["behind-cdn","cwe-601","echo","go","package","self-hosted"],"not_affected_if":["https-redirect-only","no-www-redirect-middleware","proxy-strips-forwarded-headers"],"how_to_check":"- Run `go list -m github.com/labstack/echo/v5` and `go list -m github.com/labstack/echo/v4` to read the Echo versions in the module graph.\n- Search the code for `WWWRedirect(` or `NonWWWRedirect(` to see whether the affected middleware is in use.","fix":"- Upgrade `github.com/labstack/echo/v5` to `5.1.1` or later.\n- Upgrade `github.com/labstack/echo/v4` to `4.15.2` or later.\n- If upgrading is not possible, have the edge proxy overwrite or remove the `X-Forwarded-Proto`, `X-Forwarded-Protocol` and `X-Url-Scheme` request headers.","status":"open","published_at":"2026-10-28T21:04:10+00:00","first_seen_at":"2026-10-28T21:07:45+00:00","triaged_at":"2026-10-28T21:09:31+00:00","updated_at":"2026-10-28T21:09:31+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-10-28T21:09:31Z","model":"claude-haiku-5-5","output":{"fix":"- Upgrade `github.com/labstack/echo/v5` to `5.1.1` or later.\n- Upgrade `github.com/labstack/echo/v4` to `4.15.2` or later.\n- If upgrading is not possible, have the edge proxy overwrite or remove the `X-Forwarded-Proto`, `X-Forwarded-Protocol` and `X-Url-Scheme` request headers.","reach":"internet","title":"Echo: X-Forwarded-Proto header injects arbitrary URI schemes into redirects","impact":"low","summary":"Echo's WWWRedirect and NonWWWRedirect middlewares build the Location header from the X-Forwarded-Proto request header without validating it. An attacker can make the server return a redirect to a javascript, data, file or similar scheme URL, enabling open redirects and possible cache poisoning behind a CDN.","category":"package","nicknames":[],"who_cares":["go","echo","self-hosted","behind-cdn"],"confidence":0.8,"needs_auth":"no","worst_case":"Attacker crafts redirect Location headers using javascript or file schemes","analyst_note":"","how_to_check":"- Run `go list -m github.com/labstack/echo/v5` and `go list -m github.com/labstack/echo/v4` to read the Echo versions in the module graph.\n- Search the code for `WWWRedirect(` or `NonWWWRedirect(` to see whether the affected middleware is in use.","needs_analyst":false,"not_affected_if":["https-redirect-only","proxy-strips-forwarded-headers","no-www-redirect-middleware"],"who_is_affected":"Applications written in Go that use Echo v4 below 4.15.2 or Echo v5 below 5.1.1 and register the WWWRedirect or NonWWWRedirect middleware (or their WithConfig variants). HTTPSRedirect, HTTPSWWWRedirect and HTTPSNonWWWRedirect hardcode https:// and are not affected. Exposure is greatest when the app is not behind a proxy that strips the forwarded-scheme headers.","user_interaction":"yes","needs_special_setup":"yes","severity_if_unknown":"medium"},"cost_usd":0.000821,"input_tokens":4390,"output_tokens":764,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-118658':16A,24A '-181':98C,154C '-184':165C '-2026':15A,23A '-601':35B '/labstack/echo/v4':30A,328C '/labstack/echo/v5':27A,323C '/path':175C,192C '172':164C '23wf':19A '2953':364C '301':186C '8pcj':21A '92cp':20A 'accept':332C 'access':259C 'actual':309C 'affect':151C,212C,218C 'allow':138C 'app':229C 'arbitrari':3A,143C,225C 'attack':64B,140C,159C 'attacker-control':158C 'back':357C 'behind':32B,88B,232C,244C 'behind-cdn':31B 'browser':262C 'build':48B 'c':278C 'c.istls':283C 'c.request.header.get':288C 'c.scheme':93C,269C 'cach':86B,241C,248C 'cannot':373C 'cdn':33B,90B,246C 'code':304C 'compon':152C 'concept':173C 'configur':263C 'confirm':193C 'construct':135C 'context':279C 'context.go:162':97C,153C 'context.scheme':330C 'control':160C 'could':256C 'cve':14A,22A 'cwe':34B 'data':75B,197C 'disclosur':302C 'echo':1A,36B,42B,96C,314C 'edg':377C 'enabl':81B 'example.com':178C 'fall':356C 'file':76B,199C,258C 'fix':265C,319C 'forward':12A,56B,103C,107C,181C,239C,343C,347C,385C,389C 'ftp':200C 'func':277C 'get':174C 'ghsa':18A 'ghsa-23wf-92cp-8pcj':17A 'github.com':26A,29A,322C,327C 'github.com/labstack/echo/v4':28A,326C 'github.com/labstack/echo/v5':25A,321C 'go':37B,276C 'gopher':203C 'hardcod':220C 'header':51B,59B,115C,150C,354C,397C 'headerxforwardedproto':289C 'host':41B,177C 'http':122C,273C,301C,310C,334C,359C 'http/1.1':176C,185C 'https':124C,275C,285C,297C,299C,335C 'httpsnonwwwredirect':215C 'httpsredirect':213C 'httpswwwredirect':214C 'impact':221C 'inject':5A,142C,194C,255C 'javascript':74B,183C,196C 'key':251C 'latest':316C 'locat':50B,148C,189C 'make':66B 'manual':306C 'master':317C 'method':94C,156C 'middlewar':8A,47B,129C 'middleware/redirect.go':163C 'move':187C 'nonwwwredirect':46B,128C,207C 'open':82B,222C 'overwrit':379C 'packag':38B 'patch':318C,369C 'path':253C 'perman':188C 'poison':87B,242C 'possibl':85B 'proof':171C 'proto':13A,57B,104C,182C,240C,344C,386C 'protocol':108C,348C,390C 'proxi':234C,378C 'redirect':71B,83B,136C,223C,249C 'redirectnonwww':167C 'redirectwww':166C 'remov':381C 'request':58B,114C,396C 'respons':149C,184C,250C 'return':69B,157C,272C,284C,298C,300C 'review':305C 'scheme':4A,79B,113C,133C,145C,155C,170C,195C,226C,254C,267C,280C,287C,290C,291C,294C,296C,353C,395C 'self':40B 'self-host':39B 'server':68B,311C 'similar':78B 'sourc':303C 'ssh':201C 'string':281C 'strings.tolower':292C 'strings.trimspace':293C 'strip':236C 'suggest':264C 'summari':91C 'telnet':202C 'test':312C 'trigger':257C 'trust':99C 'unsanit':132C,169C 'upgrad':366C,374C 'uri':144C 'url':80B,112C,137C,227C,352C,394C 'use':130C,168C 'v4.15.2':329C 'v5.0.4':315C 'v5.1.1':324C 'valid':61B,117C 'valu':120C,161C,363C 'variant':210C 'vbscript':198C 'verbatim':162C 'verifi':307C 'version':370C 'via':9A 'whitelist':266C 'withconfig':209C 'without':60B,116C 'workaround':365C 'ws':336C 'wss':338C 'www.example.com':191C 'www.example.com/path':190C 'wwwredirect':44B,126C,205C 'wwwredirect/nonwwwredirect':7A 'x':11A,55B,102C,106C,111C,180C,238C,342C,346C,351C,384C,388C,393C 'x-forwarded-proto':10A,54B,101C,179C,237C,341C,383C 'x-forwarded-protocol':105C,345C,387C 'x-url-schem':110C,350C,392C","nicknames":[],"mitigations":[],"who_affected":"Applications written in Go that use Echo v4 below 4.15.2 or Echo v5 below 5.1.1 and register the WWWRedirect or NonWWWRedirect middleware (or their WithConfig variants). HTTPSRedirect, HTTPSWWWRedirect and HTTPSNonWWWRedirect hardcode https:// and are not affected. Exposure is greatest when the app is not behind a proxy that strips the forwarded-scheme headers.","tier":"C","verified":{},"analyst_revisit_at":null,"first_public_at":"2026-10-28T21:04:10+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N","cvss_by":"GitHub","poc_count":0,"sources":[{"source":"ghsa","external_id":"GHSA-23wf-92cp-8pcj","url":"https://github.com/advisories/GHSA-23wf-92cp-8pcj","severity":"medium","published_at":"2026-10-28T21:04:10+00:00","modified_at":"2026-10-28T21:04:12+00:00","first_seen_at":"2026-10-28T21:07:45+00:00","fetched_at":"2026-10-28T21:07:45+00:00","note":null},{"source":"nvd","external_id":"CVE-2026-118658","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-118658","severity":null,"published_at":"2026-10-28T21:16:55+00:00","modified_at":"2026-10-28T21:16:55+00:00","first_seen_at":"2026-10-28T21:35:45+00:00","fetched_at":"2026-10-28T21:35:45+00:00","note":null}],"documents":[],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}