mirror of
https://github.com/qingchencloud/clawpanel.git
synced 2026-08-07 06:33:58 +08:00
fix(ci): validate paths consistently across platforms
This commit is contained in:
@@ -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::<Vec<_>>()
|
||||
.join(&separator.to_string())
|
||||
}
|
||||
|
||||
fn bind_openclaw_cli_path(cli_path: &std::path::Path) -> Result<(), String> {
|
||||
|
||||
@@ -930,11 +930,19 @@ fn collect_video_urls(value: &Value) -> Vec<String> {
|
||||
|
||||
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]
|
||||
|
||||
Reference in New Issue
Block a user