sand-boxer/scripts/smoke-bwrap-runtime.py
tegwick d69827aaa2 feat: pin bwrap rein runtimes and isolate private state
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0726e-5232-73f2-aaca-2c05ceb62efb
2026-09-05 20:36:11 +02:00

105 lines
4.3 KiB
Python

"""Prove a real rein CLI starts in a pinned, read-only owner runtime.
No credential acquisition or model request is performed.
"""
from __future__ import annotations
import argparse
import json
import subprocess
import tempfile
from pathlib import Path
from sandboxer.extensions.bwrap import BwrapExtension
from sandboxer.models import Profile
PROBE = r'''
import json, os, subprocess, sys
from pathlib import Path
import rein_aharness.adapter
import llm_connect
source = Path(sys.argv[1])
runtime = Path('/opt/sandboxer/runtime')
home = Path(os.environ['HOME'])
private = home / 'private-state-proof'
private.write_text('non-secret private state\n')
assert not home.is_relative_to(Path.cwd())
assert (home.stat().st_mode & 0o777) == 0o700
assert private.is_file()
try:
(runtime / 'write-probe').write_text('must be refused')
except OSError:
readonly = True
else:
readonly = False
assert readonly
assert not source.exists()
help_result = subprocess.run(['rein-aharness', '--help'], capture_output=True, timeout=15)
assert help_result.returncode == 0
assert b'usage:' in help_result.stdout
assert subprocess.check_output(['git', 'status', '--porcelain', '--ignored=matching']) == b''
interfaces = [line.split(':', 1)[0].strip()
for line in Path('/proc/net/dev').read_text().splitlines()[2:]]
assert interfaces == ['lo']
print(json.dumps({'rein_cli_started': True, 'adapter_imported': True,
'runtime_readonly': readonly, 'source_absent': True,
'home_outside_workspace': True, 'home_mode': '0700',
'worktree_clean': True, 'interfaces': interfaces,
'python_prefix': sys.prefix,
'credential_refs': json.loads(os.environ['SANDBOXER_CREDENTIAL_ROUTE_REFS'])}))
'''
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--runtime-path", required=True)
parser.add_argument("--runtime-sha256", required=True)
args = parser.parse_args()
with tempfile.TemporaryDirectory(prefix="sandboxer-runtime-proof-") as temporary:
root = Path(temporary)
source = root / "source"
source.mkdir()
subprocess.run(["git", "init", "-q", str(source)], check=True)
extension = BwrapExtension({
"base_dir": str(root / "sandboxes"),
"runtime": {"path": args.runtime_path, "sha256": args.runtime_sha256},
})
profile = Profile(id="profile.runtime-proof", version="1", extension="ext.bwrap")
handle = extension.provision(profile, {"repo": str(source)}, "localhost")
try:
extension.wait_ready(handle)
result = extension.execute(
handle, ["python3", "-c", PROBE, str(source)],
credential_route_refs=[],
execution_context={"actor": "agt", "project": "sand-boxer-runtime-proof",
"run_id": "sand-wp-0015-proof"},
timeout_seconds=30, max_output_bytes=65536,
)
persistence = extension.execute(
handle, ["python3", "-c",
"import os; from pathlib import Path; "
"assert (Path(os.environ['HOME']) / 'private-state-proof').is_file()"],
credential_route_refs=[],
execution_context={"actor": "agt", "project": "sand-boxer-runtime-proof",
"run_id": "sand-wp-0015-proof"},
timeout_seconds=15, max_output_bytes=1024,
)
finally:
teardown = extension.teardown(handle)
passed = result["exit_code"] == 0 and not result["timed_out"]
facts = json.loads(result["stdout"]) if passed else {}
private_state_persisted = persistence["exit_code"] == 0
passed = passed and private_state_persisted and teardown["workspace_removed"] == "True"
print(json.dumps({
"ok": passed, "sandbox_id": handle["sandbox_id"],
"runtime_sha256": args.runtime_sha256, "proof": facts,
"workspace_removed": teardown["workspace_removed"] == "True",
"exit_code": result["exit_code"], "model_run_proven": False,
"private_state_persisted": private_state_persisted,
}, indent=2))
return 0 if passed else 1
if __name__ == "__main__":
raise SystemExit(main())