GHSA-v753-g4cw-jm48 - Echo has Open Redirect via Control-Character Prefix Defeating sanitizeURI
## 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
MEDIUM
Severity & confidence
Source severitymedium
Platform severitymedium
Confidencehigh
Exploitationunknown
CVSS6.1
Affected
Vendorsgithub
Productsgithub.com/labstack/echo/v5github.com/labstack/echo/v4
Reporting sources (2)
GitHub Security Advisories
NIST NVD - National Vulnerability Database
Timeline & provenance
Published2026-10-28T21:04:22
Last updated2026-10-31T21:01:43
Ingested2026-10-28T21:09:19
FreshnessNEAR-REAL-TIME
Threat typeadvisory
Recommended action
Review the advisory and upgrade affected packages to the first patched version.
Next steps
- Identify affected systems in your environment.
- Apply the vendor patch or mitigation guidance.
- Review logs for indicators described in the advisory.
- Follow the affected vendor/product to track updates.
Confidence explanation
Reported by a government or cert-grade source (CISA, NCSC, NVD, ENISA, MSRC).
Source type: vendor ยท Original: GitHub Security Advisories