fix(orchestrator): ship no bytecode cache from the repository into the install

install copied the gitignored __pycache__ directories of the sandbox-writable tree into ~/.local/share/kvb-orchestrator with cp -a. Python loads a cached .pyc whose header matches the source mtime and size, and cp -a keeps the mtime, so a .pyc planted by a sandboxed agent would have run in the host runner and PermissionRequest hook without showing in any diff. install now removes every __pycache__ right after the copy; the compose build reads the same cleaned directory.

🎯 Fix: 95 %
💥 Break: 2 %
💸 Cost: –
⏱️ Time: –
🛡️ Security: 100 %
🏆 Score: 93
🚦 Gate: ✅ 90/5, cost and time <= 100, security 100 %

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kevin Veen-BirkenbachandClaude Opus 5.5 committed 2026-11-06 22:40:46 +00:00
1 parent 6f940b4415
commit de574d5c3d
2 files changed
+10

No files matched your search

+2
View File
@@ -140,6 +140,8 @@ install_hub() {
mkdir -p "${HUB}" "${STATE}" "${APPROVALS}" "${COUNCIL}" "${HOME}/.claude/projects" "${HOME}/Repositories" "${HOME}/.local/share/worktrees" "${UNITS}" "${APPROVERS}" mkdir -p "${HUB}" "${STATE}" "${APPROVALS}" "${COUNCIL}" "${HOME}/.claude/projects" "${HOME}/Repositories" "${HOME}/.local/share/worktrees" "${UNITS}" "${APPROVERS}"
chmod 700 "${APPROVERS}" chmod 700 "${APPROVERS}"
cp -a "${REPO_ROOT}/orchestrator/." "${HUB}/" cp -a "${REPO_ROOT}/orchestrator/." "${HUB}/"
# Python loads a cached .pyc whose header matches the source mtime and size, and cp -a keeps the mtime: one planted in the sandbox-writable tree would run on the host
find "${HUB}" -name __pycache__ -type d -prune -exec rm -rf {} +
chmod +x "${HUB}/client/permission_hook.py" "${HUB}/client/runner.py" "${HUB}/client/approval.py" chmod +x "${HUB}/client/permission_hook.py" "${HUB}/client/runner.py" "${HUB}/client/approval.py"
log "skills: the PermissionRequest hook client is ${HUB}/client/permission_hook.py" log "skills: the PermissionRequest hook client is ${HUB}/client/permission_hook.py"
log "skills: approvals need a pinned passkey: settings, 'Passkey registrieren', then 'make orchestrator-pin CREDENTIAL=<blob>'; until then every executor refuses" log "skills: approvals need a pinned passkey: settings, 'Passkey registrieren', then 'make orchestrator-pin CREDENTIAL=<blob>'; until then every executor refuses"
+8
View File
@@ -137,6 +137,14 @@ class TestOrchestratorMigration(unittest.TestCase):
legacy_calls = [call for call in second["calls"][len(first["calls"]) :] if any(OLD in arg for arg in call)] legacy_calls = [call for call in second["calls"][len(first["calls"]) :] if any(OLD in arg for arg in call)]
self.assertEqual(legacy_calls, [["docker", "image", "inspect", f"{OLD}:local"], ["claude", "mcp", "get", OLD]]) self.assertEqual(legacy_calls, [["docker", "image", "inspect", f"{OLD}:local"], ["claude", "mcp", "get", OLD]])
def test_install_ships_no_bytecode_from_the_tree(self):
planted = REPO_ROOT / "orchestrator" / "client" / "__pycache__" / "planted.cpython-0.pyc"
planted.parent.mkdir(exist_ok=True)
planted.write_bytes(b"planted")
self.addCleanup(planted.unlink, True)
self.install()
self.assertEqual(sorted((self.home / ".local" / "share" / NEW).rglob("__pycache__")), [])
def test_old_names_live_only_in_the_migration(self): def test_old_names_live_only_in_the_migration(self):
done = subprocess.run(["git", "grep", "-niE", "kvb[-_]hub", "--", ".", ":!docs/requirements", f":!{Path(__file__).relative_to(REPO_ROOT)}"], cwd=REPO_ROOT, capture_output=True, text=True, check=False) done = subprocess.run(["git", "grep", "-niE", "kvb[-_]hub", "--", ".", ":!docs/requirements", f":!{Path(__file__).relative_to(REPO_ROOT)}"], cwd=REPO_ROOT, capture_output=True, text=True, check=False)
hits = sorted(line.split(":", 2)[0] + ":" + line.split(":", 2)[2].strip() for line in done.stdout.splitlines()) hits = sorted(line.split(":", 2)[0] + ":" + line.split(":", 2)[2].strip() for line in done.stdout.splitlines())