@@ -679,22 +679,17 @@ def _validate_path_no_traversal(path: Path | str) -> bool:
679679 True if path is safe (no traversal components), False otherwise
680680
681681 """
682- path_str = str (path )
683- # Check for path traversal attempts
684- # Check for absolute paths that might escape (additional safety check)
685- # Note: We allow absolute paths as they're needed for worktree paths
686- return ".." not in path_str
687-
688- def _resolve_path (path : Path | str ) -> Path :
689- # Use strict=False so we don't fail on paths that don't exist yet (e.g. worktree paths)
690- # SECURITY: Validate path before resolution to prevent traversal attacks
691- if not _validate_path_no_traversal (path ):
692- error_msg = f"Path contains traversal components: { path } "
693- raise ValueError (error_msg )
694- return Path (path ).resolve (strict = False )
682+ try :
683+ path_obj = Path (path )
684+ except (ValueError , OSError ):
685+ return False
686+ else :
687+ # Check if any part is exactly '..' (not just containing '..' as a substring)
688+ # This avoids false positives like files named "config..bak"
689+ return ".." not in path_obj .parts
695690
696- def _resolve_path_consistent (path : Path | str ) -> Path :
697- """Resolve path consistently: use strict resolution if path exists, otherwise non-strict.
691+ def _resolve_path_safely (path : Path | str ) -> Path :
692+ """Resolve path, preferring strict resolution but falling back to non-strict.
698693
699694 SECURITY: This function validates paths to prevent traversal attacks before resolution.
700695 Paths should come from trusted sources (git operations, file system discovery),
@@ -716,42 +711,34 @@ def _resolve_path_consistent(path: Path | str) -> Path:
716711 raise ValueError (error_msg )
717712
718713 path_obj = Path (path )
719- if path_obj . exists () :
720- try :
721- return path_obj .resolve ()
722- except (OSError , RuntimeError ):
723- return _resolve_path ( path )
724- return _resolve_path ( path )
714+ try :
715+ # Prefer strict resolution if path exists, otherwise use non-strict
716+ return path_obj . resolve ( strict = True ) if path_obj . exists () else path_obj .resolve (strict = False )
717+ except (OSError , RuntimeError ):
718+ # Fallback to non-strict resolution on errors
719+ return path_obj . resolve ( strict = False )
725720
726721 # Resolve all root paths to absolute paths for consistent comparison
727722 # Use consistent resolution: strict for existing paths, non-strict for non-existent
728- tests_root_resolved = _resolve_path_consistent (tests_root )
729- module_root_resolved = _resolve_path_consistent (module_root )
723+ tests_root_resolved = _resolve_path_safely (tests_root )
724+ module_root_resolved = _resolve_path_safely (module_root )
730725
731726 # Resolve ignore paths and submodule paths
732- ignore_paths_resolved = [_resolve_path_consistent (p ) for p in ignore_paths ]
733- submodule_paths_resolved = [_resolve_path_consistent (p ) for p in submodule_paths ]
727+ ignore_paths_resolved = [_resolve_path_safely (p ) for p in ignore_paths ]
728+ submodule_paths_resolved = [_resolve_path_safely (p ) for p in submodule_paths ]
734729
735730 # We desperately need Python 3.10+ only support to make this code readable with structural pattern matching
736731 for file_path_path , functions in modified_functions .items ():
737732 _functions = functions
738733 # SECURITY: Validate file path before processing to prevent traversal attacks
734+ # Note: Paths come from trusted sources (git operations), but we validate defensively
739735 if not _validate_path_no_traversal (file_path_path ):
740- logger .warning (f"Skipping file with traversal components: { file_path_path } " )
741- continue
742- # Resolve file path to absolute path
743- # Convert to Path if it's a string (e.g., from get_functions_within_git_diff)
744- file_path_obj = Path (file_path_path )
745- # Use consistent resolution: try strict first (for existing files), fall back to non-strict
746- if file_path_obj .exists ():
747- try :
748- file_path_resolved = file_path_obj .resolve ()
749- except (OSError , RuntimeError ):
750- file_path_resolved = _resolve_path (file_path_path )
751- else :
752- file_path_resolved = _resolve_path (file_path_path )
753-
754- file_path = str (file_path_obj )
736+ error_msg = f"Path contains traversal components: { file_path_path } "
737+ logger .error (error_msg )
738+ raise ValueError (error_msg )
739+ # Resolve file path to absolute path using consolidated resolution logic
740+ file_path_resolved = _resolve_path_safely (file_path_path )
741+ file_path = str (file_path_path ) # Keep original path string for compatibility
755742
756743 # Check if file is in tests root using resolved paths
757744 try :
0 commit comments