Vision: Transform
palmshed/sandboxfrom working code into a reliable runtime and trusted infrastructure for AI agent platforms, code evaluation systems, and CI runners.
To prevent documentation drift across the repository:
ROADMAP.mddescribes direction, milestones, and architectural progression.- The Gist records current validation state, verified capabilities, and benchmark profiles. (Living engineering log: https://gist.github.com/bniladridas/e2a499783be6d2b9de4dd7cf4f34ee7d)
- Tests (
compliance/,tck/,sdk/typescript/src/test/) define what is actually guaranteed.
"An engineer should be able to discover
palmshed/sandbox, understand its guarantees, install it, run an example, and integrate it into an AI agent or CI workflow without needing a personal explanation."
- Supported: The sandbox enforces and tests this boundary. Verified via integration test suite and CI.
- Experimental: Implemented but still under active validation or hardware/OS capability testing.
- Unsupported: The API schema or capability negotiation may acknowledge the concept, but no enforcement guarantee currently exists.
Before marking security and resource enforcement capabilities complete, the project maintains an explicit threat model:
- What the sandbox protects against: CPU hogging/infinite loops, memory exhaustion (OOM), unhandled child process leaks, disk space flooding, unauthorized network access (when network isolation is enabled).
- What it does not protect against (Native backend): Kernel vulnerabilities / kernel exploits without isolation backends (Docker/Firecracker), hardware side-channel attacks (e.g. Spectre/Meltdown).
- Host Assumptions: Host OS kernel is secure, running with appropriate permissions (e.g., cgroups v2 / namespaces configured where applicable).
- Supported Isolation Boundaries: Clearly documented per backend (
nativevsdockervsfirecracker).
Goal: Anyone can install and run
palmshed/sandboxwithout knowing the internals.
- Runtime specification v0.1.0 (
spec/) - TypeScript reference SDK (
sdk/typescript) - Basic execution & real-time stdout/stderr streaming
- Virtual filesystem operations & initial TCK/compliance suite
- Maintain
examples/consumer-testas a permanent downstream consumer verification project - Verify npm package installation directly from tarball (
.tgz) and npm registry (examples/consumer-test/run.sh+registry-installCI job) - Comprehensive usage documentation (creation, command execution, filesystem, streaming, destruction)
- Document version compatibility rules and keep examples updated with every API change (
examples.ymlfreshness CI runs all four examples against the packed artifact;spec/compatibility.md+deprecations.md)
Success Criteria: A new engineer can clone the repo and run a sandbox example in minutes.
Goal: Turn capability flags into verified runtime guarantees ("This sandbox enforces the boundaries it documents"). Rule: Capabilities change from
false→trueonly when backed by integration tests. Status: All items below are implemented, locally verified, and CI-verified across the Ubuntu/macOS/Windows matrix (36/36 SDK tests, 31/31 conformance/TCK, 15/15 repros on macOS; Windows network/POSIX repros auto-skip where the capability is unavailable). Closeout audit completed 2026-08-08. ThecpuQuotaand Docker-network scope decisions (2026-08-08) were resolved by explicit classification rather than implementation; Docker's unverified capability flags were demoted tofalsein the same session (see §3).
- POSIX process tree discovery (group PIDs & sub-shell descendants)
- Windows process tree termination (
taskkill /F /Tequivalent) - Orphan process detection integration test suite
-
destroy()during active streaming/background process execution - Timeout cleanup regression test suite across platforms
- Native CPU time limit enforcement (process-group sampling,
ERR_CPU_EXCEEDED; commit240f2a5) - Native memory limit enforcement (process-group RSS polling,
ERR_OOM_EXCEEDED; commitsbf5cc32+91debc8) - Virtual filesystem disk quota enforcement (
ERR_DISK_QUOTA_EXCEEDED; commit85f477a) - Structured failure states and error types (
ERR_OOM_EXCEEDED,ERR_DISK_QUOTA_EXCEEDED,ERR_CPU_EXCEEDED) - Backend capability contract unit and integration tests:
memoryLimits: trueandcpuLimits: trueverified via 36/36 SDK + 31/31 conformance/TCK tests - Recursive process-tree cleanup after resource-limit kills (commit
2ee1f24) - Scope decision (2026-08-08):
cpuQuota(hard core quota, cgroups v2 / Job Objects) is classified experimental / out-of-scope for the current Native capability contract. CPU time budget (cpuTimeLimit→ERR_CPU_EXCEEDED) is the verified Phase 2 guarantee. Core quota is a different semantic (hardware core pinning vs. time accounting) and must not be conflated withcpuLimits. It remains schema-acknowledged (cpuQuotainsandbox.schema.json/exec.schema.json) but is NOT enforced by the Native backend and will be revisited as its own design item (not part of the Phase 2 closeout).
- Security threat model document (RFC 0004 threat model defined; 8 guarantees verified)
- Native backend isolation design decision (
rfcs/0004-network-isolation.md) - Native backend
network: 'disabled'implementation:- Linux:
unshare -n --user --map-root-usernetwork namespace isolation, with init-time probe and proxy-env fallback when user namespaces are unavailable (commit9b9c3f1, fixedf590557) - macOS:
sandbox-execwith Seatbelt profile (commit9b9c3f1, deprecation risk documented) - Windows: Unsupported (documented in platform matrix)
- Linux:
- Adversarial network leak test suite (5/5 PASS):
- TCP outbound blocking (commit
9b9c3f1) - UDP outbound blocking (commit
780f385) - DNS resolution blocking (commit
9b9c3f1) - Localhost service access blocking (commit
9b9c3f1) - Child process isolation inheritance (commit
780f385)
- TCP outbound blocking (commit
- Scope decision (2026-08-08): the Docker backend
--network noneleak-check suite is explicitly out of scope for Phase 2. Phase 2's network guarantee is scoped to the Native backend (unshare/sandbox-exec). Docker-backend network isolation is tracked as a separate backend-parity work item (#4) outside the Phase 2 closeout. - Scope decision (2026-08-08): the Docker backend's unverified capability flags are demoted to
false.docker.tsreportedcpuLimits: true,memoryLimits: true, andnetworkIsolation: truewithout implementation or integration-test coverage, violating the capability-promotion rule. They now reportfalse(Docker keepsfilesystem: trueandstreaming: true), enforced by an explicit capability-matrix compliance test (compliance/backends/docker.test.js). Docker CPU/memory enforcement and network isolation are future work (#4) and must land implementation and integration tests before their flags return totrue.
- Implementation exists in the native backend engine
- Public API behavior and boundary contracts are fully documented
- Clear failure modes and error types are defined for limit breaches
- Negative Boundary Test Requirement: Every capability MUST have a negative test proving explicit, controlled failure and sandbox health when the boundary is breached (e.g., exceeding memory triggers
ERR_OOM_EXCEEDEDwhile leaving the sandbox engine healthy and reusable). - Integration tests cover both standard and adversarial cases (fork bombs, memory leaks, unkilled child processes)
- CI suite verifies behavior consistently across target platforms
- Documentation & Gist updated with verified guarantee levels
Every guarantee and every reported bug gets a standalone repro (repro/<area>/*.js) that prints expected behavior and exits non-zero when the guarantee is violated. Workflow: repro → confirm it fails → automated test → fix → keep the regression test. Run with node repro/run.js (network repros auto-skip when networkIsolation is unavailable; add --all-network to force them). New capability work should land a matching repro in the same change.
Goal: Prove the sandbox solves actual production problems cleanly.
- AI Agent Runner (
examples/ai-agent-runner.mjs)- Workflow:
User Request → Agent → Sandbox → Execute Code → Return Output - Validates: Node.js code execution, sandbox isolation (network disabled), timeout handling, stdout/stderr streaming
- Workflow:
- Code Evaluation System (
examples/code-evaluator.mjs)- Workflow:
Submission → Sandbox → Run Tests → Collect Results - Validates: Multi-test execution, failed programs, infinite loops, timeout enforcement
- Workflow:
- Build / Test Environment (
examples/ci-runner.mjs)- Workflow:
Repository → Sandbox FS → npm test → Logs + Artifacts - Validates: Workspace mounting (uploadFile), build + test execution, artifact extraction (readFile/downloadFile), failure and timeout handling, sandbox reuse after failed/timed-out workloads
- All four examples run in CI via
examples.yml, which installs the packed@palmshed/sandboxtarball (never the workspace build) and runs them on Ubuntu, macOS, and Windows
- Workflow:
Goal: Make untrusted execution verifiably safe against adversarial workloads.
Status: Complete for the v1.0 scope (2026-08-08), with RFC 0006 OS-level filesystem isolation shipped in v1.1.0 (2026-09-06) as an optional, capability-reported extension. Residual items:
- OS-level filesystem isolation for the Native backend: implemented on Linux (Landlock confinement runner + runtime allowlist: escape suite 15/15 + full SDK suite 59/59 on Ubuntu 24.04 kernel 6.8.0 ABI 4) and macOS (Seatbelt profile via
sandbox-exec, allow-default with targeted denies; full E1-E10 escape suite green on macOS), reported at runtime asosFilesystemIsolation(supported|unsupported|unknown) only after a real confined self-test passes on that host. Windows reportsunsupported(AppContainer per-path FS grants require package identity; restricted tokens cannot deny reads of world-readable files, so the RFC 0006 read-denial guarantee is not met; rationale recorded in RFC 0006)- Windows network isolation: unsupported (RFC 0004; no unprivileged mechanism)
- Docker resource/network enforcement: enforced since backend-parity work item
#4(cpuLimits,memoryLimits,networkIsolationalltruewith integration coverage)- Hard
cpuQuota: designed in RFC 0007 (throttle, never kill), specified under Unreleased target 1.2.0, reported via thecpuQuotaLimitscapability. Native Linux implemented and validated green on real Linux (quota suites need a private scope); native Windows implemented and validated green on real Windows (Job Objects with per-exec self-assign prefix); Docker implemented and validated green on CI Ubuntu (daemon API probe)
- CPU Hardening: Infinite loops, runaway processes, strict timeout enforcement (CPU time budget enforced; hard core quota deferred post-v1.0)
- Memory Hardening: Large allocations, OOM handling, cleanup after process kill
- Filesystem Hardening: VFS boundary v0.1.2 (traversal / absolute-path / symlink-escape rejection,
workDircontainment, exec-path disk quota with rollback); OS-level isolation implemented post-v1.0 as an optional capability (RFC 0006, issue#3) - Process Hardening: Recursive child process cleanup, signal handling, forced termination
Success Criteria: A malicious or broken workload cannot escape or degrade the host environment (within the documented v1.0 boundary).
Goal: Make integration intuitive and self-documenting.
- TypeScript API documentation and automated reference doc generation (
docs/api.md+ Typedoc fromsdk/typescript/src/index.tsvianpm run docs;docs.ymlfails CI if generation breaks) - Practical recipes and common integration pattern examples
- Actionable error messages detailing root cause and recovery steps (
docs/errors.md: error code, meaning, cause, recovery, sandbox-reuse expectation) - Built-in debug logging mode (
SANDBOX_LOG=debug, off by default; lifecycle/resource events to stderr, consistent across native and Docker backends, never secrets/command/filesystem content) - Ergonomic API refinements for
sandbox.exec(),sandbox.writeFile(),sandbox.readFile(), andsandbox.destroy()
Goal: Guarantee stability for high-throughput, long-running systems. Status: Complete (2026-08-09). Crash recovery (
#10) closed the phase; see RFC 0005.
- Concurrency Testing: 10 concurrent sandboxes + 8 parallel executions in a single sandbox (stress suite,
sdk/typescript/src/test/stress.test.ts) - Lifecycle Stress Testing: 50 rapid create → destroy cycles and destroy-while-in-flight (
stress.test.ts); separate crash/destroy coverage in lifecycle test suite - Crash Recovery (#10): Graceful cleanup upon host process crash or unexpected backend disconnection; RFC 0005 defines the failure model, guarantees (G1-G8), and reaper design. Implemented via in-process signal/exit hooks (graceful) plus a shared registry + stale-sandbox reaper that runs at sandbox creation (post-mortem, PID-reuse safe via host start-time token). Covered by 6 integration tests (
crash.test.ts) and 3 repros (repro/crash/); platform matrix and limitations documented in RFC 0005 anddocs/api.md - Longer Concurrent Execution Testing: sustained concurrent workload test (10 sandboxes × 3 staggered rounds interleaving healthy executions, CPU-budget kills, reuse probes, and concurrent destroy). The
d760757Windows flake reproduced ona136c7a(a singleechoexceeded the 10s timeout while the other test file's PowerShell CIM samplers saturated the 2-vCPU runner) and was fixed rather than masked:node --test --test-concurrency=1serializes the SDK test files so each test's internal concurrency is preserved without cross-file CPU starvation (3 consecutive green Windows runs on8d9f40e) - Multi-Platform CI Matrix: Automated CI verification on Ubuntu, macOS, and Windows (
ci.yml+compliance.ymlmatrices, commitebd32be) - Reproducible Guarantee Lab in CI:
node repro/run.jsruns in the CI matrix with capability-aware network skip
Goal: Enable operators to inspect runtime behavior and rely on predictable performance.
- Observability: unique
execution_id, fine-grained timing metrics, peak resource reporting (peakMemoryBytesbest-effort on result and metadata; issue#8narrowed scope delivered) - Benchmark harness (
benchmarks/, informational, never gated): cold-init/cold-create/warm-create split, overhead vs a semantically equivalent baseline on representative workload v1, parallel ramp with saturation guardrails and highest-successful-N, per-sandbox host overhead; every result carries a pinned runner fingerprint and no number is a promise until explicitly promoted (seebenchmarks/README.md) - Benchmark baselines (targets, awaiting reproducible evidence):
- Cold create (after init)
<50 msnative; one-time cold init reported separately with no target - Execution overhead
<5%on representative workload v1 (raw walls recorded beside the ratio) - Concurrent sandbox capacity (
100+parallel instances without degradation; highest successful N recorded) - Memory overhead per sandbox (
<10 MBhost overhead, idle sandboxes)
- Cold create (after init)
Goal: Ready for widespread external production adoption. Plan: The freeze criteria and mechanics are tracked in
docs/release-readiness.md. The spec is frozen at 1.0.0 as of 2026-08-09.
- Stable, frozen public API schema (
spec/v1.0.0) - Semantic versioning guarantees and complete CHANGELOG
- Migration & Compatibility Policy:
- Strict 6-month deprecation window for non-breaking schema field transitions (written into
spec/deprecations.md; binding at v1.0.0) - Explicit supported Node.js runtime matrix (LTS versions:
engines >=20insdk/typescript/package.json;ci.ymlnode-ltsjob verifies Node 20 + 22 on Ubuntu, macOS, and Windows) - Native backend driver compatibility matrix across Linux distributions / macOS (documented in
docs/release-readiness.mdwith per-platform verified/best-effort status)
- Strict 6-month deprecation window for non-breaking schema field transitions (written into
- All examples verified against release tarball in CI (
examples.ymlpacks the SDK, installs the tarball into the repo-rootnode_modules, then runs all four examples on Ubuntu, macOS, and Windows) - Package published to npm registry with zero-dependency core engine (
@palmshed/sandbox@1.0.0published aslatest;filesallowlist shipsdist/+LICENSE+README.md,sdk/typescript/README.mdadded,enginesdeclared)
Goal: Release confidence comes from an adversarial, packed-artifact gate, not only from unit and integration suites. Status: Complete (2026-08-09).
production/ships a scenario runner, residue detection, eight consumer-workflow scenarios, and a soak driver; CI wires it against the packed npm tarball on the 3-OS matrix (production.yml) with nightly soak and an exact-version gate (scheduled-tests.yml). Validation recorded 2026-08-09: Production Validation 8/8 scenarios + soak smoke passed against the packed artifact on the Ubuntu/macOS/Windows matrix in the same session (run31319381753). A dedicatedcrash-recoveryscenario was added afterwards to validate issue #10 across process boundaries against the packed artifact. The suite surfaced and the session fixed three Windows-only bugs that the 44-test SDK suite missed: a single-shotfs.rmdestroy race (retried removal + unregister infinally), a registry-entry resurrection on destroy (serialized pgid writes awaited by unregister), and quadratic reaping on Windows (host start-token cached per PID; O(n²) PowerShell spawns per reap eliminated). A path-separator portability bug in theresiliencescenario was also fixed.
- Runner (
production/run.mjs): scenario discovery, per-scenario timing budgets, step timing,--list/--only/--verbose, summary table, non-zero exit on failure or residue. - Residue detection (
production/lib/residue.mjs): leaked sandbox dirs, leaked registry entries, processes holding sandbox dirs (Linux/proc, POSIXlsof +L1), registry pgid snapshots with live-process checks. - Consumer-workflow scenarios: AI coding agent (streaming, patch, test rerun, artifact byte-compare), CI runner (green build → regression → artifact preserved), code evaluation platform (20 sandboxes, mixed pass/fail/timeout/CPU-kill outcomes, pool 8, reuse after kill).
- Adversarial scenarios: concurrency (50 sandboxes + 20 parallel execs in one), recovery (quota+timeout, CPU under concurrency, destroy-while-running, crash, 50 create/destroy cycles), resilience (malformed input, workDir auto-create/traversal, env overrides vs host allowlist, symlinks, 2000-file tree, 4 MiB stdout/stderr byte-exact).
- Soak (
production/soak/soak.mjs): N sandboxes × read/write/exec cycles for a duration; reports iterations, throughput, failures; nightly--minutes 5 --sandboxes 25. - Signal-death correctness fix (found by the
recoveryscenario): a signal-killed workload (e.g.process.abort()) was reported ascompletedwithexitCode 0; the native backend now reportsfailedwith128 + signalNumberand records the signal in metadata.
Deliberate expansion beyond the released runtime. Each unit follows
spec → smallest implementation → compliance → real consumer → evidence → release, one unit at a time, and none is started without a concrete
requirement. No open issue tracks these yet by design.
| Unit | Track | Goal | State |
|---|---|---|---|
| F1 | Rust SDK | Second SDK proving the spec is language-independent (own OS glue, no Node) | Released v0.1.0 (sdk/rust/, RFC 0008): contract + basic suites green on 3 OS, consumer example, cross-checked against TypeScript |
| F2 | Go SDK | Same contract in Go | Released go-v0.1.0 (sdk/go/, RFC 0009): guarded terminal state, concurrent drains, 19 tests green under mandatory -race on all three OSes, consumer example, cross-language cancellation check with discrepancy 001 recorded |
| F3 | Python SDK | Same contract in Python | Released py-v0.1.0 (sdk/python/, RFC 0011): async-first guarded state, concurrent drains, 20 contract tests green on 3 OS × Python 3.11/3.14, consumer example, TS cross-check |
| F4 | Firecracker backend | MicroVM isolation engine | Blocked on P1 infrastructure (deferred 2026-10-14): no KVM-capable host available; local Lima/Colima/Docker excluded, no remote host identified; asset pipeline is proposal-only; RFC 0012 governs resume |
| F5 | WASI backend | WebAssembly execution model | Not started |
| F6 | Remote daemon backend | Execution over a remote boundary (would make remoteExecution true) |
Not started |
| F7 | Host mounts | Explicit opt-in host-path exposure under the filesystem-isolation model | Not started |
Maintain the central project Gist alongside every capability transition as a cumulative engineering log (preserving past validation history while appending new revisions):
- Overview & Purpose
- Architecture & Design Principles
- Current Capability Status (Supported / Experimental / Unsupported)
- Integration Examples & Consumer Verification
- Security Model & Isolation Boundaries
- Benchmarks & Performance Profile
- Validation & Test Results History (preserve timeline of verified runs)
- Known Limitations
- Roadmap Progress & Milestone Audit Log