{"record":{"id":"b9944b001dbef213","repo":"seanmonstar/warp","slug":"uri-is-a-valid-headervalue","errorCode":null,"errorMessage":"Uri is a valid HeaderValue","messagePattern":"Uri is a valid HeaderValue","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"info","filePath":"src/redirect.rs","lineNumber":144,"sourceCode":"mod sealed {\n    use bytes::Bytes;\n    use http::{header::HeaderValue, Uri};\n\n    /// Trait for redirect locations. Currently only a `Uri` can be used in\n    /// redirect.\n    /// This sealed trait exists to allow adding possibly new impls so other\n    /// arguments could be accepted, like maybe just `warp::redirect(\"/v2\")`.\n    pub trait AsLocation: Sealed {}\n    pub trait Sealed {\n        fn header_value(self) -> HeaderValue;\n    }\n\n    impl AsLocation for Uri {}\n\n    impl Sealed for Uri {\n        fn header_value(self) -> HeaderValue {\n            let bytes = Bytes::from(self.to_string());\n            HeaderValue::from_maybe_shared(bytes).expect(\"Uri is a valid HeaderValue\")\n        }\n    }\n}\n","sourceCodeStart":126,"sourceCodeEnd":148,"githubUrl":"https://github.com/seanmonstar/warp/blob/ff34d7213ed55ec342304aa7ff6ac4b351da9e66/src/redirect.rs#L126-L148","documentation":"When you pass an `http::Uri` as a redirect location, warp converts it to a `HeaderValue` via `HeaderValue::from_maybe_shared(bytes).expect(\"Uri is a valid HeaderValue\")` (src/redirect.rs:144). The conversion can only fail if the Uri's serialization contains bytes illegal in an HTTP header value (e.g. control characters like \\r or \\n). Warp panics because a parsed `Uri` should already have excluded such bytes — a header-injection safety invariant.","triggerScenarios":"`warp::redirect(uri)` (or `redirect_found`/`see_other`) with a `Uri` that somehow contains forbidden header bytes — practically unreachable via normal `Uri::from_str` parsing, but possible with permissively constructed Uri instances.","commonSituations":"Not normally hit; relevant if Uri values are built from untrusted string fragments and passed through low-level `http::Uri` constructors that bypass strict validation.","solutions":["Build the redirect target with `Uri::from_str` / `http::Uri` validation rather than manual construction","Sanitize user-supplied redirect targets (reject control characters and CR/LF) before redirecting","Prefer `warp::redirect(String::parse::<Uri>()?)`-style validated input over raw concatenation","Guard against open-redirect while you're at it: restrict targets to your own origin"],"exampleFix":"// before\nlet uri: http::Uri = unsafe_target_parse_somehow();\nwarp::redirect(uri);\n// after\nlet uri: http::Uri = target.parse().map_err(|_| warp::reject::bad_request())?;\nif uri.to_string().bytes().any(|b| b < 0x21 || b == 0x7f) { return Err(warp::reject::bad_request()); }\nwarp::redirect(uri);","handlingStrategy":"validation","validationCode":"fn safe_redirect_target(s: &str) -> Result<http::Uri, warp::Rejection> {\n    let uri: http::Uri = s.parse().map_err(|_| warp::reject::bad_request())?;\n    if uri.to_string().bytes().any(|b| b < 0x21 || b == 0x7f) {\n        return Err(warp::reject::bad_request());\n    }\n    Ok(uri)\n}","typeGuard":"fn is_header_safe(s: &str) -> bool {\n    s.bytes().all(|b| (0x21..=0x7e).contains(&b) || b >= 0x80)\n}","tryCatchPattern":null,"preventionTips":["Construct redirect targets from strictly parsed http::Uri values","Reject control characters and CR/LF in any user-influenced redirect input","Also guard against open redirects by whitelisting allowed hosts"],"tags":["http","redirect","panic","header-injection"],"backgroundTag":"internal-invariant-violation","analyzedSha":"ff34d7213ed55ec342304aa7ff6ac4b351da9e66","analyzedAt":"2026-09-09T16:57:46.316Z","contentChangedAt":"2026-09-09T16:57:46.316Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}