Description
The crates.io backend keeps a small middleware in src/middleware/svelte_redirect.rs that redirects leftover /svelte/... URLs from the old SvelteKit preview to the same path without the prefix. The redirect_target() function only checked that the stripped remainder was empty or started with /:
if !(stripped.is_empty() || stripped.starts_with('/')) {
return None;
}
A request path of /svelte/\evil.com (a raw backslash, not %5C) passes this check, so the redirect target becomes /\evil.com and Redirect::temporary() writes it into the Location header unchanged. Three details make this reachable:
- The
normalize_pathmiddleware, which runs outermost, only rewrites paths containing//or/.. It neutralizes the//evil.comvariant but leaves/\evil.comuntouched. - hyper and the
httpcrate accept a raw backslash in the request path.PATH_MAPinhttp'ssrc/uri/path.rsmarks0x40..=0x5Fas valid. - axum's
Redirectperforms no validation of scheme-relativeLocationvalues.
Browsers implement the WHATWG URL standard, which treats \ as / in special schemes, so a scheme-relative /\evil.com is parsed as //evil.com.
Proof of Concept:
GET https://HOSTNAME/svelte/\evil.com
-> 307 Location: /\evil.com
-> browser navigates to https://evil.com
Impact
An attacker can build a link that starts on the trusted crates.io host and lands on a site under their control, which is useful for phishing. In practice the production deployment was not exploitable at the time of the report because the Fastly CDN in front of crates.io rejects such request paths. The bug would have become real if the CDN configuration changed or a direct hostname for the backend were exposed, so it was reported privately to the Rust security team rather than as a public issue.
Solution
Fixed in rust-lang/crates.io#14579, merged on 2026-09-03. Non-root redirect targets must now start with an ASCII letter after the leading slash, which rules out any destination a client could read as another host.
Timeline
- 2026-09-01: Report sent to the Rust security team.
- 2026-09-03: Fix merged into crates.io main.