MEDIUMCVSS v3.1 6.1Vulnerability

CVE-2026-118656

## Summary Echo's dedicated open-redirect guard, `sanitizeURI`, decides whether a redirect target is a local path by inspecting exactly two byte positions: `uri[0]` and `uri[1]`. If the value begins with a control character such as a tab or a newline, followed by a separator pair, the guard does not fire and the value is written to the `Location` header unchanged. Browsers remove tab and newline characters from URLs before parsing them, and treat a backslash as a forward slash for HTTP and HTTPS URLs. A `Location` value of ``/\t/attacker.example`` is therefore resolved by the browser as an absolute URL on `attacker.example`. Confirmed end to end in a headless browser. ## Technical background ### The guard `middleware/slash.go:144` (duplicated verbatim at `echo.go:958`): ```go func sanitizeURI(uri string) string { // double slash `\\`, `//` or even `\/` is absolute uri for browsers and by redirecting request to that uri // we are vulnerable to open redirect attack. so replace all slashes from the beginning with single slash if len(uri) > 1 && (uri[0] == '\\' || uri[0] == '/') && (uri[1] == '\\' || uri[1] == '/') { uri = "/" + strings.TrimLeft(uri, `/\`) } return uri } ``` The condition is anchored at absolute offsets 0 and 1. It cannot see a separator that has been shifted by one byte. ### Data flow 1. `RemoveTrailingSlash` (`middleware/slash.go:112-140`) reads `url.Path`, which `net/http` has already percent-decoded, strips the trailing slash, and appends the raw query string: ```go path := url.Path ... if l > 0 && strings.HasSuffix(path, "/") { path = path[:l] uri := path if qs != "" { uri += "?" + qs } if config.RedirectCode != 0 { return c.Redirect(config.RedirectCode, sanitizeURI(uri)) // line 132 } ``` 2. `AddTrailingSlash` does the same in the opposite direction at `middleware/slash.go:67`. 3. A request for `/%09/attacker.example/x/` has `url.Path` equal to `"/\t/attacker.example/x/"` (a literal TAB

Properties

Severity
medium
Summary
Echo has Open Redirect via Control-Character Prefix Defeating sanitizeURI
Nvd fetched at
2026-10-28T23:43:43.157973+00:00
Cvss severity
MEDIUM
Cvss score
6.1
Retrieved at
2026-10-28T23:45:49+00:00
Ghsa published
2026-10-28T21:04:22Z
Source url
https://github.com/advisories/GHSA-v753-g4cw-jm48
Ghsa updated
2026-10-28T21:04:23Z
Ghsa id
GHSA-v753-g4cw-jm48
Last source
GitHub Advisory Database
Score
6.1
Cvss version
3.1
Cve id
CVE-2026-118656
Cvss vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
First seen by Signal
2026-10-28T23:44:40+00:00
Is ghsa only
false
Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Published at
2026-10-28T21:16:55.550
Last modified
2026-10-28T21:16:55.550

Related Entities (5)

Explore deeper with Ninja Signal's threat intelligence graph

CVE-2026-118656 (CVSS v3.1 6.1) — Ninja Signal Threat Intelligence | Ninja Signal