Spaces:
Sleeping on Zero
Sleeping on Zero
File size: 6,534 Bytes
9fca766 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | """Sandbox tests: VFS, shell, puzzles, fabrication, mirror, and the
no-real-filesystem tripwire."""
from pathlib import Path
import pytest
from scrypt.sandbox.fabricate import fabricate_home
from scrypt.sandbox.mirror import mirror_home
from scrypt.sandbox.puzzles import plant_all
from scrypt.sandbox.shell import Shell
from scrypt.sandbox.vfs import VFS, VfsError
def make_shell(seed: int = 1) -> Shell:
vfs = VFS()
fabricate_home(vfs, seed=seed)
return Shell(vfs)
# ---------------------------------------------------------------------- vfs
def test_vfs_write_read_roundtrip():
vfs = VFS()
vfs.write("/home/drifter/a/b.txt", "hello")
assert vfs.read("/home/drifter/a/b.txt") == "hello"
assert vfs.read("~/a/b.txt") == "hello"
def test_vfs_relative_paths_and_dotdot():
vfs = VFS()
vfs.write("~/x/deep/file.txt", "v")
vfs.chdir("~/x/deep")
assert vfs.read("file.txt") == "v"
assert vfs.read("../deep/file.txt") == "v"
vfs.chdir("..")
assert vfs.cwd_path == "/home/drifter/x"
def test_vfs_remove_counts_files():
vfs = VFS()
for i in range(5):
vfs.write(f"~/photos/{i}.jpg", "x")
assert vfs.remove("~/photos", recursive=True) == 5
assert vfs.resolve("~/photos") is None
with pytest.raises(VfsError):
vfs.remove("~/photos")
# -------------------------------------------------------------------- shell
def test_shell_ls_hides_dotfiles_without_dash_a():
sh = make_shell()
plain = sh.run("ls").out
assert ".bash_history" not in plain
assert ".bash_history" in sh.run("ls -a").out
def test_shell_pipe_cat_grep():
sh = make_shell()
out = sh.run("cat documents/todo.txt | grep insurance").out
assert "insurance" in out and "gym" not in out
def test_shell_grep_file_directly():
sh = make_shell()
assert "insurance" in sh.run("grep insurance documents/todo.txt").out
def test_shell_glob_expansion():
sh = make_shell()
sh.vfs.chdir("~/photos/vacation")
out = sh.run("ls *.jpg").out
assert "IMG_" in out
def test_shell_find_by_name():
sh = make_shell()
out = sh.run("find / -name todo.txt").out
assert "/home/drifter/documents/todo.txt" in out
def test_shell_rm_reports_deletions():
sh = make_shell()
sh.run("rm -r photos")
assert sh.last_deletions >= 5
def test_shell_revocation():
sh = make_shell()
sh.run("grep x documents/todo.txt")
sh.revoke("grep", "no more needles.")
result = sh.run("grep x documents/todo.txt")
assert "command not found" in result.err and "needles" in result.err
assert "grep" not in sh.available()
def test_most_used_tracks_and_excludes_revoked():
sh = make_shell()
for _ in range(3):
sh.run("ls")
sh.run("pwd")
assert sh.most_used() == "ls"
sh.revoke("ls")
assert sh.most_used() == "pwd"
def test_unknown_command():
sh = make_shell()
assert "command not found" in sh.run("vim todo.txt").err
# ------------------------------------------------------------------ puzzles
def test_zip_puzzle_solvable_via_history():
sh = make_shell(seed=3)
puzzles = {p.id: p for p in plant_all(sh.vfs, seed=3)}
# The password is in .bash_history
history = sh.run("cat ~/.bash_history").out
password = next(
word.rstrip(",") for line in history.splitlines() if "# pw" in line
for word in [line.split()[2]]
)
sh.run(f"cd ~/downloads")
assert "inflating" in sh.run(f"unzip severance.zip {password}").out
assert puzzles["zip_password"].poll(sh) is not None
assert puzzles["zip_password"].solved
def test_zip_rejects_wrong_password():
sh = make_shell(seed=3)
plant_all(sh.vfs, seed=3)
assert "incorrect password" in sh.run("unzip ~/downloads/severance.zip guess").err
def test_hidden_dir_puzzle_requires_reading_manifest():
sh = make_shell(seed=3)
puzzles = {p.id: p for p in plant_all(sh.vfs, seed=3)}
assert puzzles["hidden_dir"].poll(sh) is None
sh.run("cat ~/.warden/manifest.txt")
reward = puzzles["hidden_dir"].poll(sh)
assert reward is not None and reward.kind == "card"
def test_cron_defusal_by_rm():
sh = make_shell(seed=3)
puzzles = {p.id: p for p in plant_all(sh.vfs, seed=3)}
assert puzzles["cron_defusal"].poll(sh) is None
sh.run("rm /etc/cron.d/reinforcement")
reward = puzzles["cron_defusal"].poll(sh)
assert reward is not None and reward.kind == "mercy"
# -------------------------------------------------------------- ingestion
def test_fabricate_is_deterministic():
a, b = VFS(), VFS()
fabricate_home(a, seed=9)
fabricate_home(b, seed=9)
assert [p for p, _ in a.iter_files()] == [p for p, _ in b.iter_files()]
def test_mirror_filters_secrets_and_caps(tmp_path: Path):
(tmp_path / "notes").mkdir()
(tmp_path / "notes" / "diary.txt").write_text("dear diary")
(tmp_path / ".ssh").mkdir()
(tmp_path / ".ssh" / "id_rsa").write_text("PRIVATE KEY")
(tmp_path / "api_token.txt").write_text("sk-12345")
(tmp_path / "big.txt").write_text("x" * 100_000)
(tmp_path / "photo.png").write_bytes(b"\x89PNG....")
vfs = VFS()
mirror_home(vfs, source=tmp_path)
files = dict(vfs.iter_files())
assert files["/home/drifter/notes/diary.txt"].content == "dear diary"
assert not any(".ssh" in p for p in files)
assert not any("api_token" in p for p in files)
# Oversized text and binary files come through as name-only stubs.
assert files["/home/drifter/big.txt"].content == "<mirrored file>"
assert files["/home/drifter/photo.png"].content == "<mirrored file>"
def test_mirror_never_writes_to_host(tmp_path: Path):
(tmp_path / "a.txt").write_text("hi")
before = sorted(p.name for p in tmp_path.rglob("*"))
vfs = VFS()
mirror_home(vfs, source=tmp_path)
vfs.remove("/home/drifter/a.txt") # the Warden deletes the COPY
after = sorted(p.name for p in tmp_path.rglob("*"))
assert before == after
def test_vfs_and_shell_never_import_os():
"""The tripwire: only mirror.py may touch the host filesystem."""
import scrypt.sandbox.puzzles as puzzles
import scrypt.sandbox.shell as shell
import scrypt.sandbox.vfs as vfs
for module in (vfs, shell, puzzles):
source = Path(module.__file__).read_text()
assert "import os" not in source, f"{module.__name__} imports os"
assert "pathlib" not in source, f"{module.__name__} imports pathlib"
assert "open(" not in source, f"{module.__name__} calls open()"
|