diff --git a/tools/ci/src/common.rs b/tools/ci/src/common.rs index c46bf45d1..3716e1172 100644 --- a/tools/ci/src/common.rs +++ b/tools/ci/src/common.rs @@ -1069,7 +1069,7 @@ pub(crate) async fn download_s3_prefix( if relative.is_empty() { continue; } - let output = target.join(relative); + let output = safe_download_target(target, relative)?; if let Some(parent) = output.parent() { tokio::fs::create_dir_all(parent) .await @@ -1248,6 +1248,17 @@ pub(crate) fn path_to_s3_key(path: &Path) -> String { .join("/") } +fn safe_download_target(target: &Path, relative: &str) -> Result { + let candidate = Path::new(relative); + for component in candidate.components() { + ensure!( + matches!(component, std::path::Component::Normal(_)), + "Refusing to write S3 object outside download target: {relative}" + ); + } + Ok(target.join(candidate)) +} + pub(crate) async fn download_file(url: &str, path: &Path) -> Result<()> { let bytes = Client::new() .get(url)