Files
troupe-standup/wizard-work/beam/test_path_sandbox.py

74 lines
2.5 KiB
Python

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()