from pathlib import Path import pytest from sandboxer.extensions import runtime_store from sandboxer.extensions.runtime import runtime_digest, verified_runtime @pytest.fixture def inputs(tmp_path, monkeypatch): home = tmp_path / "owner-home" home.mkdir(mode=0o700) monkeypatch.setenv("HOME", str(home)) source = tmp_path / "candidate" (source / "bin").mkdir(parents=True) (source / "pyvenv.cfg").write_text("home = /usr/bin\n") (source / "bin/python3").write_bytes(b"fixture executable") (source / "bin/python3").chmod(0o755) (source / "bin/python").symlink_to("python3") return source, home / "runtimes", runtime_digest(source) def test_install_preserves_pin_and_does_not_share_mutable_source(inputs): source, store, digest = inputs result = runtime_store.install_runtime(source, store, digest) installed = verified_runtime(result) assert installed == store / digest assert store.stat().st_mode & 0o777 == 0o700 assert not result["profile_activated"] assert not result["credential_delivery_configured"] assert (installed / "bin/python").is_symlink() (source / "bin/python3").write_bytes(b"changed after installation") assert verified_runtime(result) == installed def test_repeat_is_idempotent_but_never_repairs_or_overwrites_existing_artifact(inputs): source, store, digest = inputs first = runtime_store.install_runtime(source, store, digest) assert runtime_store.install_runtime(source, store, digest)["reused"] installed = Path(first["runtime"]["path"]) target = installed / "bin/python3" target.write_bytes(b"tampered installed artifact") with pytest.raises(ValueError, match="digest"): runtime_store.install_runtime(source, store, digest) assert target.read_bytes() == b"tampered installed artifact" def test_wrong_digest_refuses_before_creating_store(inputs): source, store, _ = inputs with pytest.raises(ValueError, match="digest"): runtime_store.install_runtime(source, store, "0" * 64) assert not store.exists() def test_copy_tampering_never_publishes(inputs, monkeypatch): source, store, digest = inputs copytree = runtime_store.shutil.copytree def corrupt(src, dst, *args, **kwargs): result = copytree(src, dst, *args, **kwargs) if Path(src) == source: (Path(dst) / "bin/python3").write_bytes(b"corrupted during copy") return result monkeypatch.setattr(runtime_store.shutil, "copytree", corrupt) with pytest.raises(ValueError, match="digest"): runtime_store.install_runtime(source, store, digest) assert not (store / digest).exists() assert not list(store.glob(".install-*")) @pytest.mark.parametrize("mode", [0o777, 0o775, 0o755]) def test_store_must_be_private(inputs, mode): source, store, digest = inputs store.mkdir(mode=mode) store.chmod(mode) with pytest.raises(ValueError, match="permissions"): runtime_store.install_runtime(source, store, digest) assert not (store / digest).exists() def test_store_symlink_is_refused(inputs): source, store, digest = inputs actual = store.parent / "actual" actual.mkdir(mode=0o700) store.symlink_to(actual) with pytest.raises(ValueError, match="canonical"): runtime_store.install_runtime(source, store, digest) @pytest.mark.parametrize("mode", [0o777, 0o4755, 0o2755]) def test_even_a_matching_pin_cannot_admit_unsafe_artifact_modes(inputs, mode): source, store, _ = inputs (source / "bin/python3").chmod(mode) digest = runtime_digest(source) with pytest.raises(ValueError, match="unsafe permission"): runtime_store.install_runtime(source, store, digest) assert not (store / digest).exists() def test_world_writable_parent_is_refused(inputs): source, store, digest = inputs store.parent.chmod(0o777) with pytest.raises(ValueError, match="permissions"): runtime_store.install_runtime(source, store, digest) def test_store_outside_owner_home_is_refused(inputs): source, store, digest = inputs with pytest.raises(ValueError, match="below the owner home"): runtime_store.install_runtime(source, store.parent.parent / "other", digest)