@@ -6,6 +6,7 @@ fn normalize_unicode(input: &str) -> String {
66}
77
88/// Sanitize file path to prevent directory traversal attacks
9+ /// This version rejects absolute paths - suitable for user input
910pub fn sanitize_file_path ( path : & str ) -> Result < PathBuf , & ' static str > {
1011 // Check for null bytes which are used in many exploits
1112 if path. contains ( '\0' ) {
@@ -14,16 +15,16 @@ pub fn sanitize_file_path(path: &str) -> Result<PathBuf, &'static str> {
1415
1516 // Unify separators for traversal check
1617 let unified_path = path. replace ( '\\' , "/" ) ;
17- let path_obj = Path :: new ( & unified_path) ;
1818
19- // Check if the path is absolute (which we don't allow)
20- if path_obj . is_absolute ( ) {
19+ // Reject absolute paths
20+ if unified_path . starts_with ( '/' ) || unified_path . starts_with ( "//" ) {
2121 return Err ( "Absolute paths are not allowed" ) ;
2222 }
2323
24- // Reject any path that contains ".." as a component
25- for component in path_obj. components ( ) {
26- if let std:: path:: Component :: ParentDir = component {
24+ // Check for traversal patterns in the unified path
25+ // Split by separator and check each component
26+ for component in unified_path. split ( '/' ) {
27+ if component == ".." {
2728 return Err ( "Path contains directory traversal sequences" ) ;
2829 }
2930 }
@@ -33,7 +34,40 @@ pub fn sanitize_file_path(path: &str) -> Result<PathBuf, &'static str> {
3334 let original_path_obj = Path :: new ( path) ;
3435 let normalized = normalize_path ( original_path_obj) ;
3536
36- // Final check on normalized path
37+ // Final check on normalized path for directory traversal
38+ for component in normalized. components ( ) {
39+ if let std:: path:: Component :: ParentDir = component {
40+ return Err ( "Path attempts to escape parent directory" ) ;
41+ }
42+ }
43+
44+ Ok ( normalized)
45+ }
46+
47+ /// Sanitize file path allowing absolute paths - for internal use
48+ /// This version allows absolute paths but still prevents directory traversal
49+ pub fn sanitize_file_path_internal ( path : & str ) -> Result < PathBuf , & ' static str > {
50+ // Check for null bytes which are used in many exploits
51+ if path. contains ( '\0' ) {
52+ return Err ( "Path contains null bytes" ) ;
53+ }
54+
55+ // Unify separators for traversal check
56+ let unified_path = path. replace ( '\\' , "/" ) ;
57+
58+ // Check for traversal patterns in the unified path
59+ // Split by separator and check each component
60+ for component in unified_path. split ( '/' ) {
61+ if component == ".." {
62+ return Err ( "Path contains directory traversal sequences" ) ;
63+ }
64+ }
65+
66+ // For the actual path object we return, we use the original path but normalized
67+ let original_path_obj = Path :: new ( path) ;
68+ let normalized = normalize_path ( original_path_obj) ;
69+
70+ // Final check on normalized path for directory traversal
3771 for component in normalized. components ( ) {
3872 if let std:: path:: Component :: ParentDir = component {
3973 return Err ( "Path attempts to escape parent directory" ) ;
0 commit comments