From d5ceccdf98d79c373a3ca050c0a19b780d5c5810 Mon Sep 17 00:00:00 2001 From: Chrislearn Young Date: Thu, 19 Sep 2024 12:37:13 +0800 Subject: [PATCH] security fix: Under Windows, you can jump out of the serve dir to access any file on the server --- crates/serve-static/src/dir.rs | 4 ++++ crates/serve-static/src/lib.rs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/serve-static/src/dir.rs b/crates/serve-static/src/dir.rs index a6eb39ab7..beffa67a9 100644 --- a/crates/serve-static/src/dir.rs +++ b/crates/serve-static/src/dir.rs @@ -322,6 +322,10 @@ impl Handler for StaticDir { if self.include_dot_files || !is_dot_file { for root in &self.roots { let raw_path = join_path!(root, &rel_path); + // Security check to ensure that the accessed path is a subpath of the current root path. + if !Path::new(&raw_path).starts_with(root) { + continue; + } for filter in &self.exclude_filters { if filter(&raw_path) { continue; diff --git a/crates/serve-static/src/lib.rs b/crates/serve-static/src/lib.rs index 7d5230336..3d21075b4 100644 --- a/crates/serve-static/src/lib.rs +++ b/crates/serve-static/src/lib.rs @@ -59,7 +59,7 @@ pub(crate) fn format_url_path_safely(path: &str) -> String { let final_slash = if path.ends_with('/') { "/" } else { "" }; let mut used_parts = Vec::with_capacity(8); for part in path.split(['/', '\\']) { - if part.is_empty() || part == "." { + if part.is_empty() || part == "." || (cfg!(windows) && part.contains(':')) { continue; } else if part == ".." { used_parts.pop();