import os, tempfile, unittest from path_sandbox import PathEscapeError, safe_join, safe_resolve, is_within, realpath_root class TestPathSandbox(unittest.TestCase): def setUp(self): self.d = tempfile.mkdtemp() self.root = os.path.join(self.d, "root") os.makedirs(self.root) self.rr = os.path.realpath(self.root) # a file inside with open(os.path.join(self.root, "a.txt"), "w") as f: f.write("x") # subdir os.makedirs(os.path.join(self.root, "sub")) # symlink escaping root os.symlink("/etc", os.path.join(self.root, "escape")) def test_basic_join(self): self.assertEqual(safe_join(self.root, "a.txt"), os.path.join(self.rr, "a.txt")) def test_nested(self): self.assertEqual(safe_join(self.root, "sub", "b.txt"), os.path.join(self.rr, "sub", "b.txt")) def test_traversal_rejected(self): with self.assertRaises(PathEscapeError): safe_join(self.root, "..", "etc", "passwd") def test_absolute_rejected(self): with self.assertRaises(PathEscapeError): safe_join(self.root, "/etc/passwd") def test_backslash_rejected(self): with self.assertRaises(PathEscapeError): safe_join(self.root, "a\\..\\..\\etc") def test_nul_rejected(self): with self.assertRaises(PathEscapeError): safe_join(self.root, "a\x00b") def test_symlink_escape_rejected(self): with self.assertRaises(PathEscapeError): safe_join(self.root, "escape", "passwd") def test_empty_root_error(self): with self.assertRaises(PathEscapeError): realpath_root("") def test_nonexistent_root_error(self): with self.assertRaises(PathEscapeError): realpath_root(os.path.join(self.d, "nope")) def test_is_within_true(self): self.assertTrue(is_within(self.root, os.path.join(self.root, "a.txt"))) def test_is_within_false(self): self.assertFalse(is_within(self.root, "/etc/passwd")) def test_safe_resolve_list(self): self.assertEqual(safe_resolve(self.root, ["sub", "x"]), os.path.join(self.rr, "sub", "x")) def test_dot_components_ok(self): # single "." components collapse p = safe_join(self.root, ".", "a.txt") self.assertEqual(p, os.path.join(self.rr, "a.txt")) def test_double_slash_ok(self): p = safe_join(self.root, "sub//b.txt") self.assertEqual(p, os.path.join(self.rr, "sub", "b.txt")) if __name__ == "__main__": unittest.main()