Skip to content
Medium 6.1

Echo has Open Redirect via Control-Character Prefix Defeating sanitizeURI

CVE-2026-118656 First seen on SecPulse

Affected packages

EcosystemPackageAffectedFixed
labstack echo — —
go github.com/labstack/echo/v5
< 5.4.0
5.4.0
go github.com/labstack/echo/v4
< 4.16.0
4.16.0
Original description The description as published by the source.

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):

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…

Source: CVE.org (CVE Program・cvelistV5) NVD GitHub Advisory

References

We use cookies for analytics and ad measurement. This setting applies to all Game co., Ltd. sites. Details