PyBox
Run Python you don't trust in a fresh, sealed box on your Mac — and get a receipt that says how it knows what happened.
You give PyBox a program. It runs it once in a brand-new Linux container inside a private VM: no network, no access to your files, a read-only system, strict memory, CPU and process limits. Then it removes the box and hands you a receipt that keeps four kinds of fact apart: what was configured, what the engine and kernel observed, what the program printed, and what is still unknown.
When a job needs more, you ask for it on that run, and the receipt shows it:
numpy, pandas and matplotlib (the data image), your own pinned packages,
up to 30 seconds, and copies of files in and out. The same engine works from the command line, from Python, as an
MCP tool for AI agents (claude mcp add pybox -- pybox mcp), and in a bounded
AI repair loop where the model can only propose code.
Quickstart
Requirements: macOS on Apple Silicon, Python 3.11 or newer, and
brew install colima docker. PyBox has no Python dependencies and never installs
software for you.
git clone https://github.com/ctxnn/pybox && cd pybox
python3 -m pip install .
From PyPI, once 0.3.0 is released: pipx install pybox-sandbox (the name pybox was
taken). Either way the command is pybox and the Python import is import pybox.
Set up once
pybox setup # dry run: shows every folder, file and download first
pybox setup --yes # about 3–5 minutes, mostly the one-time VM download
pybox setup --yes --with data # optional: numpy, pandas, matplotlib, about 30 s
pybox doctor # read-only check; says what to run next
Setup creates a private ~/.pybox/runtime, starts a dedicated Colima profile
pybox (no host folders, no forwarded ports), pulls only the pinned Python
image by digest, verifies it, and stops the VM. It never overwrites a file. The
data image is built in the VM from hash-locked wheels; it is the only time a
PyBox container has the network.
Run things
pybox vm start
echo 'print(6*7)' | pybox exec -
pybox exec report.py --input sales.csv --output results/
pybox exec analysis.py --image data --timeout 20
pybox image build tools --lock tools.lock # your own packages, from uv pip compile --generate-hashes
pybox vm stop
pybox exec prints the program's output, then a short receipt (to stderr):
42
PyBox receipt · run 5319e024 · image stdlib · 0.166 s of 2 s
From the container engine checked before start, read back after
Exit code 0 (ended by itself)
Settings checked yes, before the program started
Mac folders shared none
Network none
Limits 128 MiB · 32 processes · 0.5 CPU · 2 s (+1 s box timer)
Box removed and confirmed gone
From the Linux kernel sampled while it ran, from outside the box
Memory peak 2.5 MiB of 128 MiB
Processes peak 6 of 32
CPU throttled 0 periods
From the program untrusted: a program can print or write anything
Printed 3 bytes on stdout, 0 bytes on stderr
Not known PyBox says so instead of guessing
final counters (the box can vanish between readings) · exact clock alignment
--json prints the full versioned record instead. A complete fresh-box run takes
about 0.2 s once the VM is running (performance).
Returned files are written all at once, never overwrite anything, and are marked
like downloads so macOS checks them when opened.
With an AI agent
claude mcp add pybox -- pybox mcp --images stdlib,data --max-timeout 30
The agent gets one tool, run_python, with optional image, files and
return_files. You set the ceilings; the agent can only ask for less. Program
output and returned files come back as data inside the result, never as protocol
messages. Tested with PyBox's own MCP client, Claude Code and Cursor's command-line
agent; not yet with Claude Desktop (details).
From Python
from pybox import run_container
result = run_container(open("report.py").read(), image="data", timeout_s=10,
inputs=[("sales.csv", open("sales.csv", "rb").read())],
collect_outputs=True)
print(result.record["cleanup"]["status"], [name for name, _ in result.output_files])
Tests
python3 -B -W error::ResourceWarning -m unittest discover -s tests
Expect Ran 209 tests … OK. They mock the engine and never start the VM.
What PyBox promises — and what it does not
| Promise | Evidence (dated, local) | Limit |
|---|---|---|
Each run uses a fixed policy the caller cannot change: pinned image, UID 10000, all capabilities dropped, no-new-privileges, no network, read-only root, noexec /tmp, memory = memory+swap, task, CPU and file limits, no engine logs. The policy is read back and verified before START. |
13 restriction checks (M3b), 9 resource checks (M3c) | Finite checks, not proof against arbitrary hostile code. |
Opt-in choices are fixed options, verified like everything else: the data image or your own (512 MiB, 64 tasks, 1 CPU, checked by image ID and recipe hash), deadlines up to 30 s, files copied in and out within 64 files / 8 MiB each way. |
18 live checks (M9), 11 more (M10), an independent security review | Returned files are the program's work and untrusted. Your own packages can run start-up code inside the box. |
| Execution ends even if the Mac supervisor is killed: PID 1 is a kill timer set to the wall deadline + 1 s. | Supervisor SIGKILL → stopped at 3.028 s; 30 s run stopped at 30.01 s |
Assumes a healthy, scheduled VM. Not a hard real-time bound. |
Leftovers are reclaimed by the next run or pybox cleanup, only after expiry (120 s), only if stopped and fully identity-matched. |
Step 4 real-expiry reclamation | Without another invocation, stopped objects stay indefinitely. |
| Resource facts come from the kernel (cgroup v2), read by a trusted reader outside the container — never from program output. | OOM kill, task-limit and throttling events observed (M3c, M4) | Live samples, not exact finals; clocks are not aligned. |
| MCP: one tool, bounded inputs, output nested as data. | 13 live protocol checks (M5); Claude Code and Cursor sessions (M9, M10) | Not tested with Claude Desktop or the official SDKs. |
| Repair loop: the model returns a full-source proposal; trusted code decides everything else. | 8 real sessions, 4/4 repaired per group (M6) | 4 synthetic problems; not a benchmark. |
Exit code 137 alone never establishes a cause. PyBox labels a termination
only when its own recorded KILL or the timer's timing supports it, and otherwise
says so.
Documentation
| Read | For |
|---|---|
site/ |
The documentation site (start here): install, first run, an 87-second walkthrough with captions, concepts, files, packages, CLI / Python / MCP guides, reference, performance, evidence, FAQ. Built from docs-site/ with python3 docs-site/build.py. |
| Files in and out · Packages and longer runs · MCP | The M9 features. |
| LEARNING.md | The long-form lab notebook, milestone by milestone. |
| Roadmap · Progress | Accepted contract, release gates and status. |
| Results: Step 4 · M3b · M3c · M4 · M5 · M6 · M8 · M9 · M10 | Dated real-runtime evidence and every preserved failure. |
| M10 security review | An independent adversarial review of the new surface, and how each finding was resolved. |
| Runtime ledger · Evidence archive | What exists on this machine and where raw evidence lives. |
| Final review · M7 results | Independent review findings and the M7 delivery record. |
Status
M1–M6 are complete and locally qualified. M7 (documentation, site, review) is
delivered. M8 (installable, portable paths, setup / vm / doctor) is
implemented. M9 (the data image, files in and out, runs up to 30 s, pybox exec
with a readable receipt, configurable MCP, PyPI-ready packaging, benchmarks) is
implemented, unit-tested (198 tests) and checked live in a throwaway installation;
see M9 results. M10 (matplotlib, your own images, final readings,
a 15× faster watcher, Cursor tests, an independent security review with every finding
resolved) is done; see M10 results. Not done yet: a second Mac,
Claude Desktop, a PyPI release, the Homebrew tap. Committed locally on branch
m9-useful-for-real-work; not pushed.
Contributing, security and changes
- CONTRIBUTING.md: set up, run the tests, test against a real VM safely.
- SECURITY.md: report a vulnerability privately; what's in scope.
- CHANGELOG.md: what's in each release.
License
Metadata
Release files for pybox-sandbox 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pybox_sandbox-0.3.0.tar.gz | 115.3 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pybox_sandbox-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 192.8 kB
Release files / pybox_sandbox-0.3.0.tar.gz
| Download URL | pybox_sandbox-0.3.0.tar.gz |
|---|---|
| Size | 115.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
84ec2f8b8d0ab70458be2d6495c3ddc6891638f52bc5217a7278b3a7e7433648
|
|
BLAKE2b-256 checksum How to use checksums |
9c21701fecd2abaa3196897f753be33e218fd4111a66db2cfea10ecc7d7d1412
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logRelease files / pybox_sandbox-0.3.0-py3-none-any.whl
| Download URL | pybox_sandbox-0.3.0-py3-none-any.whl |
|---|---|
| Size | 77.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3ce7e413de710fa966803f0c4c1fd17e35c62a32f616f795c5029ae60f7fd11e
|
|
BLAKE2b-256 checksum How to use checksums |
69cc72f1951a06884e13bf0107d046f595149de1b5fb6d96a0e23edbeff56440
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logSecurity for pybox-sandbox 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for pybox_sandbox-0.3.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.