the-custodian/docs/changes/netkingdom-target-2026-10-17/native-runtime-install-r3/runtime.py
codex 4016f3bdee
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Reject generated-only commits / generated-commit-guard (push) Successful in 9s
Record failed runtime trial and reviewed verification proposal (3/4)
2026-10-17 13:27:00 +02:00

52 lines
2.2 KiB
Python

"""Digest-pinned, owner-configured Python runtimes for bwrap."""
from __future__ import annotations
import hashlib
import json
import os
import stat
from pathlib import Path
RUNTIME_MOUNT = "/opt/sandboxer/runtime"
def runtime_digest(root: Path) -> str:
"""Hash the complete artifact, including modes and internal symlink targets."""
if not root.is_absolute() or root.resolve(strict=True) != root or not root.is_dir():
raise ValueError("runtime path must be a canonical absolute directory")
records = []
for path in sorted(root.rglob("*")):
mode = path.lstat().st_mode
if stat.S_ISLNK(mode):
target = os.readlink(path)
if Path(target).is_absolute() or not path.resolve(strict=True).is_relative_to(root):
raise ValueError("runtime symlink escapes the artifact")
value = ["symlink", target]
elif stat.S_ISREG(mode):
with path.open("rb") as stream:
value = ["file", hashlib.file_digest(stream, "sha256").hexdigest()]
elif stat.S_ISDIR(mode):
value = ["directory"]
else:
raise ValueError("runtime contains an unsupported special file")
records.append([path.relative_to(root).as_posix(), stat.S_IMODE(mode), *value])
return hashlib.sha256(json.dumps(records, separators=(",", ":")).encode()).hexdigest()
def verified_runtime(config: dict) -> Path | None:
"""Only owner extension configuration can select a runtime artifact."""
runtime = config.get("runtime")
if runtime is None:
return None
if not isinstance(runtime, dict) or set(runtime) != {"path", "sha256"}:
raise ValueError("runtime requires exactly path and sha256")
if not isinstance(runtime["path"], str) or not isinstance(runtime["sha256"], str):
raise ValueError("runtime path and sha256 must be strings")
root = Path(runtime["path"])
if (not (root / "pyvenv.cfg").is_file() or not (root / "bin/python3").is_file()
or (root / ".git").exists()):
raise ValueError("runtime must be a standalone Python environment, not a checkout")
if runtime_digest(root) != runtime["sha256"]:
raise ValueError("runtime artifact digest does not match owner configuration")
return root