diff --git a/wizard-work/beam/run_pathguard_tests.py b/wizard-work/beam/run_pathguard_tests.py new file mode 100644 index 0000000..263e72b --- /dev/null +++ b/wizard-work/beam/run_pathguard_tests.py @@ -0,0 +1,78 @@ +import os, tempfile, sys +sys.path.insert(0, "/root/troupe-standup/wizard-work/beam") +from pathguard import safe_join, PathTraversalError + +tests = [] +def T(name): + def dec(f): + tests.append((name, f)); return f + return dec + +@T("basic") +def _(): + with tempfile.TemporaryDirectory() as d: + out = safe_join(d, "a", "b.txt") + assert out == os.path.join(os.path.realpath(d), "a", "b.txt") + +@T("dotdot") +def _(): + with tempfile.TemporaryDirectory() as d: + try: safe_join(d, "..", "etc", "passwd") + except PathTraversalError: return + raise AssertionError("not raised") + +@T("abs") +def _(): + with tempfile.TemporaryDirectory() as d: + try: safe_join(d, "/etc/passwd") + except PathTraversalError: return + raise AssertionError("not raised") + +@T("symlink") +def _(): + with tempfile.TemporaryDirectory() as d: + base = os.path.join(d, "base"); os.makedirs(base) + target = os.path.join(d, "secret.txt") + open(target,"w").write("secret") + link = os.path.join(base, "link") + os.symlink(target, link) + try: safe_join(base, "link") + except PathTraversalError: return + raise AssertionError("symlink escape not rejected") + +@T("nested") +def _(): + with tempfile.TemporaryDirectory() as d: + sub = os.path.join(d, "sub"); os.makedirs(sub) + out = safe_join(d, "sub", "file.txt") + assert out.startswith(os.path.realpath(d) + os.sep) + +@T("empty") +def _(): + with tempfile.TemporaryDirectory() as d: + out = safe_join(d, "", None, "x") + assert out.endswith("x") + +@T("nul") +def _(): + with tempfile.TemporaryDirectory() as d: + try: safe_join(d, "a\x00b") + except PathTraversalError: return + raise AssertionError("nul not rejected") + +@T("basedir") +def _(): + with tempfile.TemporaryDirectory() as d: + f = os.path.join(d, "f"); open(f,"w").close() + try: safe_join(f, "x") + except PathTraversalError: return + raise AssertionError("base not dir not rejected") + +fails = 0 +for name, f in tests: + try: + f(); print("PASS", name) + except Exception as e: + fails += 1; print("FAIL", name, repr(e)) +print("TOTAL", len(tests), "FAILS", fails) +raise SystemExit(1 if fails else 0)