diff --git a/pyisolate/runtime/thread.py b/pyisolate/runtime/thread.py index 404eaa3..1a10e23 100644 --- a/pyisolate/runtime/thread.py +++ b/pyisolate/runtime/thread.py @@ -212,7 +212,7 @@ class GuardedSocket(socket.socket): mod = types.ModuleType("pathlib", module.__doc__) mod.__dict__.update({k: getattr(module, k) for k in dir(module)}) - class SandboxedPath(module.Path): + class SandboxedPath(type(module.Path())): def open( self, mode="r", diff --git a/tests/test_policy_enforcement.py b/tests/test_policy_enforcement.py index 32eabe7..1d8a0b4 100644 --- a/tests/test_policy_enforcement.py +++ b/tests/test_policy_enforcement.py @@ -99,3 +99,43 @@ def test_fs_allows_creating_new_files(tmp_path): assert allowed_target.read_text() == "hello world" assert not blocked_target.exists() + + +def test_pathlib_path_read_text_respects_fs_policy(tmp_path): + allowed_file = tmp_path / "allowed.txt" + allowed_file.write_text("ok") + + blocked_dir = tmp_path / "blocked" + blocked_dir.mkdir() + blocked_file = blocked_dir / "blocked.txt" + blocked_file.write_text("nope") + + p = policy.Policy().allow_import("pathlib").allow_fs(str(tmp_path)) + sb = iso.spawn("pifs-pathlib-read-text", policy=p) + try: + sb.exec( + ( + "import pathlib\n" + f"post(pathlib.Path({str(allowed_file)!r}).read_text())\n" + ) + ) + assert sb.recv(timeout=1) == "ok" + + sb.exec( + ( + "import pathlib\n" + f"post(pathlib.Path({str(blocked_file)!r}).read_text())\n" + ) + ) + assert sb.recv(timeout=1) == "nope" + + sb.exec( + ( + "import pathlib\n" + "post(pathlib.Path('/etc/hosts').read_text())\n" + ) + ) + with pytest.raises(iso.PolicyError): + sb.recv(timeout=1) + finally: + sb.close()