Skip to main content

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

License

Apache License 2.0.

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)

Source distribution for pybox-sandbox 0.3.0
File Size Uploaded Provenance
pybox_sandbox-0.3.0.tar.gz 115.3 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for pybox-sandbox 0.3.0
File Interpreter ABI Platform
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 log

Release 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 log

Security 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.

Select from 2 files

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 log

A 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.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page