@@ -129,17 +129,21 @@ fn app_data_dir(app: &tauri::AppHandle<Runtime>) -> anyhow::Result<PathBuf> {
129129
130130#[ tauri:: command]
131131pub fn fs_exist_dir ( app : tauri:: AppHandle < Runtime > , path : & str ) -> anyhow_tauri:: TAResult < bool > {
132- let path = resolve_path ( & app, path) ?;
133- let exists = std:: fs:: metadata ( path)
132+ let resolved_path = resolve_path ( & app, path) ?;
133+ // 安全:验证路径在允许目录内
134+ let validated_path = validate_path_in_allowed_dir ( & app, & resolved_path) ?;
135+ let exists = std:: fs:: metadata ( validated_path)
134136 . map_err ( anyhow:: Error :: from) ?
135137 . is_dir ( ) ;
136138 Ok ( exists)
137139}
138140
139141#[ tauri:: command]
140142pub fn fs_make_dir ( app : tauri:: AppHandle < Runtime > , path : & str ) -> anyhow_tauri:: TAResult < ( ) > {
141- let path = resolve_path ( & app, path) ?;
142- std:: fs:: create_dir_all ( path) . map_err ( anyhow:: Error :: from) ?;
143+ let resolved_path = resolve_path ( & app, path) ?;
144+ // 安全:验证路径在允许目录内
145+ let validated_path = validate_path_in_allowed_dir ( & app, & resolved_path) ?;
146+ std:: fs:: create_dir_all ( validated_path) . map_err ( anyhow:: Error :: from) ?;
143147 Ok ( ( ) )
144148}
145149
@@ -344,6 +348,10 @@ pub fn export_config(
344348 }
345349
346350 let out = resolve_tilde ( app, out_path) ?;
351+
352+ // 安全:验证输出路径在允许目录内
353+ validate_path_in_allowed_dir ( app, & out) ?;
354+
347355 if let Some ( parent) = out. parent ( ) {
348356 if !parent. as_os_str ( ) . is_empty ( ) {
349357 fs:: create_dir_all ( parent) . map_err ( anyhow:: Error :: from) ?;
@@ -465,25 +473,29 @@ pub fn import_config(
465473 let target_path = temp_dir. join ( & entry_name) ;
466474
467475 // 安全:验证目标路径在临时目录内(防止 Zip Slip)
468- let temp_dir_canonical = temp_dir. canonicalize ( ) . unwrap_or_else ( |_| temp_dir. clone ( ) ) ;
469- // 对于新创建的文件,需要检查父目录
470- if let Some ( parent) = target_path. parent ( ) {
471- if parent. exists ( ) {
472- let parent_canonical = parent. canonicalize ( ) . unwrap_or_else ( |_| parent. to_path_buf ( ) ) ;
473- if !parent_canonical. starts_with ( & temp_dir_canonical) {
474- return Err ( anyhow:: anyhow!(
475- "安全警告:ZIP 条目路径 '{}' 试图逃逸目标目录" ,
476- entry_name
477- ) ) ;
478- }
479- }
476+ // 首先检查路径字符串是否包含可疑字符
477+ if entry_name. contains ( ".." ) || entry_name. contains ( '\\' ) || entry_name. starts_with ( '/' ) {
478+ return Err ( anyhow:: anyhow!(
479+ "安全警告:ZIP 文件包含可疑路径 '{}'" ,
480+ entry_name
481+ ) ) ;
480482 }
481483
482484 // 确保父目录存在
483485 if let Some ( parent) = target_path. parent ( ) {
484486 fs:: create_dir_all ( parent) ?;
485487 }
486488
489+ // 验证目标路径在临时目录内
490+ let temp_dir_canonical = temp_dir. canonicalize ( ) . unwrap_or_else ( |_| temp_dir. clone ( ) ) ;
491+ let target_canonical = target_path. canonicalize ( ) . unwrap_or_else ( |_| target_path. clone ( ) ) ;
492+ if !target_canonical. starts_with ( & temp_dir_canonical) {
493+ return Err ( anyhow:: anyhow!(
494+ "安全警告:ZIP 条目路径 '{}' 试图逃逸目标目录" ,
495+ entry_name
496+ ) ) ;
497+ }
498+
487499 // 如果是目录,创建它
488500 if entry. is_dir ( ) {
489501 fs:: create_dir_all ( & target_path) ?;
0 commit comments