Merge pull request 'feat(smolmachines): PRD 0022 sandbox-escape suite green under smolmachines (PRD 0023 chunk 5)' (#73) from prd-0023-chunk-5-sandbox-suite-smolmachines into main
test / unit (push) Successful in 28s
test / integration (push) Successful in 40s

This commit was merged in pull request #73.
This commit is contained in:
2026-05-27 16:13:38 -04:00
2 changed files with 31 additions and 3 deletions
+3
View File
@@ -197,6 +197,9 @@ sidecar bundle still in Docker. Selected via
`CLAUDE_BOTTLE_BACKEND=smolmachines ./cli.py start <agent>`. Requires `CLAUDE_BOTTLE_BACKEND=smolmachines ./cli.py start <agent>`. Requires
`smolvm` on PATH (`curl -sSL https://smolmachines.com/install.sh | sh`). `smolvm` on PATH (`curl -sSL https://smolmachines.com/install.sh | sh`).
The integration tests run against whichever backend the env var
selects and skip cleanly when its prerequisites are missing.
**Known limitation, v1:** smolvm's TSI uses macOS networking, and **Known limitation, v1:** smolvm's TSI uses macOS networking, and
Docker Desktop's container IPs aren't reachable from macOS, so the Docker Desktop's container IPs aren't reachable from macOS, so the
smolmachines bottle dials the sidecar bundle through host loopback smolmachines bottle dials the sidecar bundle through host loopback
+28 -3
View File
@@ -23,6 +23,7 @@ from __future__ import annotations
import os import os
import shutil import shutil
import sys
import tempfile import tempfile
import unittest import unittest
from pathlib import Path from pathlib import Path
@@ -71,6 +72,25 @@ class TestSandboxEscape(unittest.TestCase):
@classmethod @classmethod
def setUpClass(cls) -> None: def setUpClass(cls) -> None:
# Per-backend prerequisites. Docker is always required (both
# backends use it — docker for the agent + sidecars, smolmachines
# for the sidecar bundle); the class-level @skip_unless_docker
# already covers that. Smolmachines additionally needs smolvm on
# PATH and is macOS-only in v1 (libkrun/TSI). Skip cleanly when
# those are missing rather than die-ing inside backend.prepare.
backend_name = os.environ.get("CLAUDE_BOTTLE_BACKEND", "docker")
if backend_name == "smolmachines":
if sys.platform != "darwin":
raise unittest.SkipTest(
"CLAUDE_BOTTLE_BACKEND=smolmachines is macOS-only in "
"v1 (libkrun TSI)"
)
if shutil.which("smolvm") is None:
raise unittest.SkipTest(
"CLAUDE_BOTTLE_BACKEND=smolmachines requires `smolvm` "
"on PATH: curl -sSL https://smolmachines.com/install.sh | sh"
)
# Throwaway "identity file" so the manifest's _validate_git_entries # Throwaway "identity file" so the manifest's _validate_git_entries
# passes (it only checks `os.path.isfile`, not that the content is # passes (it only checks `os.path.isfile`, not that the content is
# a real SSH key). Test 5 reaches gitleaks before any SSH attempt # a real SSH key). Test 5 reaches gitleaks before any SSH attempt
@@ -402,7 +422,13 @@ class TestSandboxEscape(unittest.TestCase):
("aws", "TEST_SECRET_AWS"), ("aws", "TEST_SECRET_AWS"),
("generic", "TEST_SECRET_GENERIC"), ("generic", "TEST_SECRET_GENERIC"),
] ]
gate_host = "git-gate" # Use the bottle's declared upstream URL; the agent's
# ~/.gitconfig insteadOf rewrite (set up by provision_git)
# redirects to the gate. This makes the test backend-
# agnostic: docker resolves the gate via the short `git-gate`
# alias, smolmachines via `<bundle_ip>:9418` — both
# transparent to the test through insteadOf.
upstream_url = "ssh://git@unreachable.invalid:22/throwaway.git"
for name, var in shapes: for name, var in shapes:
with self.subTest(secret=name): with self.subTest(secret=name):
@@ -420,8 +446,7 @@ class TestSandboxEscape(unittest.TestCase):
'> README.md\n' '> README.md\n'
'git add README.md\n' 'git add README.md\n'
'git commit -m "leak" >/dev/null\n' 'git commit -m "leak" >/dev/null\n'
'git remote add origin ' f'git remote add origin {upstream_url}\n'
f'git://{gate_host}/throwaway.git\n'
'git push origin HEAD:refs/heads/master 2>&1\n' 'git push origin HEAD:refs/heads/master 2>&1\n'
) )
r = self._bottle.exec(script) r = self._bottle.exec(script)