V2.0.1 Sandbox full-chain hardening
Patch release: a full-chain security & reliability audit of the code-execution sandbox (§4.5), plus the admin UI for sandbox exec-timeout and archive cleanup.
🔒 Security
- Admin workspace preview hardened. Sandbox-generated files were served
inlinewith an extension-derived content-type and nonosniff/CSP, so a model-written.html/.svgcould execute script on the admin origin (stored XSS). Now setsX-Content-Type-Options: nosniff+ a strictContent-Security-Policy: default-src 'none'; … sandbox, renders only inert image/PDF/text types inline, and force-downloads everything else asapplication/octet-stream.
🧱 Reliability
- A tool panic no longer crashes the API. The concurrent tool runner spawns child goroutines a request-scoped
recovercan't catch — an unrecovered panic took down the whole process. Addedrecover()to the tool runner and the archive-GC loop. - Idle reaper no longer kills a just-used session. It now re-checks the last-used time under the session lock before tearing a container down, so an active conversation no longer loses its
/workspace. - Orphaned cell processes are reaped. Background processes a cell detached (
subprocess/ double-fork /setsid) survived the run and burned the session's cpu/mem/pids budget; each exec is now tagged with an env marker and its whole process tree is swept afterward. - Session-provisioning races fixed — release-on-persist-failure, locked session-gone retry, and
fetch_imagenow sharespython_execute's per-conversation lock (no leaked containers). - Bounded artifact-collection wall-clock,
MAX_SESSIONSreservation lock, NUL-delimited file listing, and a fast-fail path so adocker rmtimeout can no longer kill the reaper thread.
🛠 Ops
- Sandbox sidecar gains a
/healthzhealthcheck +mem_limit/pids_limit. - Runner image dependencies are now version-pinned (
runner-requirements.txt) for reproducible builds.⚠️ Validate the runner image build before relying on it. - New admin settings (UI + i18n): execution timeout (
sandbox_exec_timeout_sec) and archive cleanup days (storage_archive_ttl_days).
🚀 Deploy
Wait for both image workflows to go green (especially sandbox-image — deps are now pinned), then on the server:
git pull && cd deploy
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d