@@ -1995,3 +1995,54 @@ def test_blocks_parent_traversal_hardlink_target(self, tmp_path):
19951995 self ._member ("link" , is_reg = False , is_lnk = True , linkname = "../outside.txt" ),
19961996 str (tmp_path ),
19971997 )
1998+
1999+
2000+ class TestIsWithinDir :
2001+ """Tests for _is_within_dir static method."""
2002+
2003+ def test_is_within_dir_absolute_paths_success (self ):
2004+ """Test _is_within_dir with absolute paths that resolve correctly."""
2005+ base = "/tmp/base"
2006+ candidate = "/tmp/base/sub/file.txt"
2007+ assert ModelManagement ._is_within_dir (base , candidate ) is True
2008+
2009+ def test_is_within_dir_absolute_paths_failure (self ):
2010+ """Test _is_within_dir with absolute paths that are outside the base."""
2011+ base = "/tmp/base"
2012+ candidate = "/tmp/other/file.txt"
2013+ assert ModelManagement ._is_within_dir (base , candidate ) is False
2014+
2015+ def test_is_within_dir_relative_paths_success (self ):
2016+ """Test _is_within_dir with relative paths that resolve inside the base."""
2017+ # abspath will resolve relative to the current working directory
2018+ base = "cache"
2019+ candidate = "cache/sub/file.txt"
2020+ assert ModelManagement ._is_within_dir (base , candidate ) is True
2021+
2022+ def test_is_within_dir_relative_paths_failure (self ):
2023+ """Test _is_within_dir with relative paths that resolve outside the base."""
2024+ base = "cache"
2025+ candidate = "cache/../../evil.txt"
2026+ assert ModelManagement ._is_within_dir (base , candidate ) is False
2027+
2028+ def test_is_within_dir_sibling_directories (self ):
2029+ """Test _is_within_dir with sibling directories sharing a prefix."""
2030+ base = "/tmp/cache"
2031+ candidate = "/tmp/cache-evil/file.txt"
2032+ assert ModelManagement ._is_within_dir (base , candidate ) is False
2033+
2034+ def test_is_within_dir_trailing_separators (self ):
2035+ """Test _is_within_dir with trailing separators."""
2036+ base = "/tmp/cache/"
2037+ candidate = "/tmp/cache/file.txt"
2038+ assert ModelManagement ._is_within_dir (base , candidate ) is True
2039+
2040+ def test_is_within_dir_same_path (self ):
2041+ """Test _is_within_dir when base and candidate are the same."""
2042+ path = "/tmp/cache"
2043+ assert ModelManagement ._is_within_dir (path , path ) is True
2044+
2045+ def test_is_within_dir_different_drives (self ):
2046+ """Test _is_within_dir when paths are on different drives (Windows)."""
2047+ with patch ("os.path.commonpath" , side_effect = ValueError ):
2048+ assert ModelManagement ._is_within_dir ("C:\\ base" , "D:\\ base" ) is False
0 commit comments