From 10f57c00e867e6917efafe7d2f0706dde2b222a9 Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Thu, 16 Apr 2026 01:23:32 +0200 Subject: [PATCH 1/4] also block XSS attempts in security middleware --- crates/bin/docs_rs_web/src/handlers/crate_details.rs | 2 +- crates/bin/docs_rs_web/src/middleware/security.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/crates/bin/docs_rs_web/src/handlers/crate_details.rs b/crates/bin/docs_rs_web/src/handlers/crate_details.rs index 6ecfad115..060642dbb 100644 --- a/crates/bin/docs_rs_web/src/handlers/crate_details.rs +++ b/crates/bin/docs_rs_web/src/handlers/crate_details.rs @@ -2227,7 +2227,7 @@ path = "src/lib.rs" .create() .await?; - let resp = env.web_app().await.get("/crate/dummy%3E").await?; + let resp = env.web_app().await.get("/crate/dummy%7B").await?; assert_eq!(resp.status(), StatusCode::BAD_REQUEST); Ok(()) diff --git a/crates/bin/docs_rs_web/src/middleware/security.rs b/crates/bin/docs_rs_web/src/middleware/security.rs index d2e76484c..630e670e9 100644 --- a/crates/bin/docs_rs_web/src/middleware/security.rs +++ b/crates/bin/docs_rs_web/src/middleware/security.rs @@ -55,6 +55,11 @@ fn validate_decoded_path(path: &str) -> Result<()> { bail!("detected `#` in request path"); } + // `<` and `>` are never allowed — they indicate HTML injection attempts. + if path.contains('<') || path.contains('>') { + bail!("detected `<` or `>` in request path"); + } + Ok(()) } @@ -96,6 +101,9 @@ mod tests { "/casual_logger/0.6.4/%2e%2e%5c%2e%2e%5c%2e%2e%5c%2e%2e%5c%2e%2e%5c%2e%2e%5c%2e%2e%5c%2e%2e"; "ends with backslash dot dot" )] + #[test_case( + "/mathru/0.10.0/i686-unknown-linux-gnu/mathru/special/hypergeometric/%3E%3Cscript%20defer%20src=%22https:/cdn.jsdelivr.net/npm/katex@0.10.1/dist/katex.min.js%22%20integrity=%22sha384-2BKqo+exmr9su6dir+qCw08N2ZKRucY4PrGQPP..." + )] async fn test_invalid_path(path: &str) -> Result<()> { let app = Router::new() .route("/{*inner}", get(|| async { StatusCode::OK })) From 009a67d052ea73bf9bfb60c7df7dae31b7bd56ee Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Thu, 16 Apr 2026 06:45:52 +0200 Subject: [PATCH 2/4] update rustls-webpki again for the next bug --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1ce176263..a5d183fd6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7057,9 +7057,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.11" +version = "0.103.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20a6af516fea4b20eccceaf166e8aa666ac996208e8a644ce3ef5aa783bc7cd4" +checksum = "8279bb85272c9f10811ae6a6c547ff594d6a7f3c6c6b02ee9726d1d0dcfcdd06" dependencies = [ "aws-lc-rs", "ring", From f66461918298a73aa20600759b6154732a1fb195 Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Thu, 16 Apr 2026 06:46:01 +0200 Subject: [PATCH 3/4] don't use <> in encoding tests --- crates/bin/docs_rs_web/src/handlers/rustdoc.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bin/docs_rs_web/src/handlers/rustdoc.rs b/crates/bin/docs_rs_web/src/handlers/rustdoc.rs index 22d9cf93e..b5b1fed50 100644 --- a/crates/bin/docs_rs_web/src/handlers/rustdoc.rs +++ b/crates/bin/docs_rs_web/src/handlers/rustdoc.rs @@ -2631,12 +2631,12 @@ mod test { assert_eq!( latest_version_redirect( "tungstenite", - "/tungstenite/0.10.0/tungstenite/?search=String+-%3E+Message", + "/tungstenite/0.10.0/tungstenite/?search=String+-%7B+Message", &env.web_app().await, env.config() ) .await?, - "/crate/tungstenite/latest/target-redirect/tungstenite/?search=String+-%3E+Message", + "/crate/tungstenite/latest/target-redirect/tungstenite/?search=String+-%7B+Message", ); Ok(()) }); @@ -3389,7 +3389,7 @@ mod test { web.assert_redirect_cached_unchecked( "/minidumper/latest/%3c%2f%73%63%72%69%70%74%3e%3c%74%65%73%74%65%3e", - "/minidumper/latest/%3C/script%3E%3Cteste%3E", + "/minidumper/latest/%3C/script%7B%3Cteste%7B", CachePolicy::ForeverInCdn(KrateName::from_str("minidumper").unwrap().into()), env.config(), ) From d3227bea97c0eae8e0a733d5fbedcec79eb906fb Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Thu, 16 Apr 2026 09:48:54 +0200 Subject: [PATCH 4/4] fix another test with now invalid encoded chars in the url --- crates/bin/docs_rs_web/src/handlers/rustdoc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bin/docs_rs_web/src/handlers/rustdoc.rs b/crates/bin/docs_rs_web/src/handlers/rustdoc.rs index b5b1fed50..99ee16e74 100644 --- a/crates/bin/docs_rs_web/src/handlers/rustdoc.rs +++ b/crates/bin/docs_rs_web/src/handlers/rustdoc.rs @@ -3388,8 +3388,8 @@ mod test { let web = env.web_app().await; web.assert_redirect_cached_unchecked( - "/minidumper/latest/%3c%2f%73%63%72%69%70%74%3e%3c%74%65%73%74%65%3e", - "/minidumper/latest/%3C/script%7B%3Cteste%7B", + "/minidumper/latest/%7d%2f%73%63%72%69%70%74%7b%7d%74%65%73%74%65%7b", + "/minidumper/latest/%7D/script%7B%7Dteste%7B", CachePolicy::ForeverInCdn(KrateName::from_str("minidumper").unwrap().into()), env.config(), )