Skip to content

feat: runtime sandbox for untrusted registry handlers (0.3.0) - #19

Merged
MarouaBoud merged 1 commit into
mainfrom
feat/registry-runtime-sandbox
Sep 4, 2026
Merged

MarouaBoud merged 1 commit into
mainfrom
feat/registry-runtime-sandbox

Conversation

@MarouaBoud

Copy link
Copy Markdown
Member

Closes the real security gap in the public registry: until now, mockworld add scanned handler code with a bypassable regex and then ran it in-process. This adds process-level isolation for untrusted (registry-installed) mocks.

Threat model — untrusted code executed at three moments, all now closed

  • mockworld add: previously called validate_mock, which imported the module to check signatures — executing untrusted code in the host before install. Now validation is static-only (import_handlers=False); nothing is imported.
  • Load: untrusted handlers.py/seed.py are no longer imported in the host process at all (loader infers trust from the install path).
  • Per call: handlers run in a persistent hardened subprocess (mockworld._sandbox_worker).

The sandbox

Before any untrusted import, the worker neuters socket, subprocess, os.system/exec*/fork, ctypes, and file writes, and sets CPU/memory rlimits. The parent keeps ownership of state and entropy: it derives the per-call keys, ships the state slice, and applies returned mutations to its own copy-on-write overlay — so a sandboxed mock is byte-identical to a trusted one and isolation stays parent-side. Locally-authored mocks stay trusted (unchanged).

Honest scope: defense-in-depth, not a formal guarantee (in-process Python can't be made perfectly escape-proof). It removes the easy paths — exfiltration, spawning processes, trashing files — and contains crashes/hangs to a disposable child holding none of the host's state. Documented: for hard isolation, run mockworld in a container.

Tests (92 total, +6)

Sandboxed mock stays byte-identical to trusted; malicious net/proc/write handlers all blocked with no side effect; add doesn't execute top-level code; validate --static doesn't import; session isolation preserved. Bumped to 0.3.0 (new security capability); twine check passes.

…process (0.3.0)

Registry-installed handler/seed code is never imported in the host process — at
add, load, or call time. It runs in a subprocess with network/subprocess/exec/
ctypes/file-writes neutered before any untrusted import, plus CPU/memory limits.
The parent owns state + entropy, so a sandboxed mock is byte-identical to a
trusted one. Closes the RCE surface from the static-only safety gate.
@MarouaBoud
MarouaBoud merged commit a6fa8a8 into main Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant