From 8cd8d2a2ad98227e7453fb3210143aad2dc45339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=99=B4=E5=A4=A9?= Date: Sun, 12 Jul 2026 13:09:20 -0700 Subject: [PATCH] fix(ci): validate paths consistently across platforms --- src-tauri/src/commands/config.rs | 15 ++++++++++----- src-tauri/src/commands/media.rs | 14 +++++++++++++- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src-tauri/src/commands/config.rs b/src-tauri/src/commands/config.rs index 64543cf..b957e75 100644 --- a/src-tauri/src/commands/config.rs +++ b/src-tauri/src/commands/config.rs @@ -7108,11 +7108,16 @@ pub fn write_panel_config(config: Value) -> Result<(), String> { } fn path_without_curdir_string(path: &std::path::Path) -> String { - let cleaned: PathBuf = path - .components() - .filter(|component| !matches!(component, std::path::Component::CurDir)) - .collect(); - cleaned.to_string_lossy().to_string() + let raw = path.to_string_lossy(); + let separator = if raw.contains('\\') { + '\\' + } else { + std::path::MAIN_SEPARATOR + }; + raw.split(['/', '\\']) + .filter(|component| *component != ".") + .collect::>() + .join(&separator.to_string()) } fn bind_openclaw_cli_path(cli_path: &std::path::Path) -> Result<(), String> { diff --git a/src-tauri/src/commands/media.rs b/src-tauri/src/commands/media.rs index 9c879db..40ab264 100644 --- a/src-tauri/src/commands/media.rs +++ b/src-tauri/src/commands/media.rs @@ -930,11 +930,19 @@ fn collect_video_urls(value: &Value) -> Vec { fn is_safe_relative_media_path(raw: &str) -> bool { let path = Path::new(raw); - if raw.trim().is_empty() || path.is_absolute() { + let bytes = raw.as_bytes(); + let has_windows_drive_prefix = + bytes.len() >= 2 && bytes[0].is_ascii_alphabetic() && bytes[1] == b':'; + if raw.trim().is_empty() + || path.is_absolute() + || raw.starts_with(['/', '\\']) + || has_windows_drive_prefix + { return false; } path.components() .all(|component| matches!(component, Component::Normal(_) | Component::CurDir)) + && raw.split(['/', '\\']).all(|component| component != "..") } fn path_compare_key(path: &Path) -> String { @@ -2088,9 +2096,13 @@ mod tests { #[test] fn media_paths_must_stay_relative_to_media_root() { assert!(is_safe_relative_media_path("assets/2026/07/job-1.png")); + assert!(is_safe_relative_media_path(r"assets\2026\07\job-1.png")); assert!(!is_safe_relative_media_path("../openclaw.json")); assert!(!is_safe_relative_media_path("assets/../../openclaw.json")); + assert!(!is_safe_relative_media_path(r"assets\..\openclaw.json")); assert!(!is_safe_relative_media_path("C:/Users/test/secret.txt")); + assert!(!is_safe_relative_media_path(r"C:\Users\test\secret.txt")); + assert!(!is_safe_relative_media_path(r"\\server\share\secret.txt")); } #[test]