pyplaypen-sandbox

One-shot subprocess sandbox for running Python inside a container.

execute(code) → JSON return value + artifacts
run_process(executable) → exit code + stdout/stderr
one shared supervisor fresh process group per call · rlimits · uid drop · timeout-kill · subreaper reaping · bounded & hashed output
each interface reaches into the same supervisor and returns what that call produced
Not a hostile-code sandbox. Code that deliberately tries to escape is held by the container around this process. This library adds depth inside that container. For escape-resistant isolation, use gVisor, Firecracker, or a VM.

What it does

Each call forks a fresh child, in its own process group, that:

Install

pip install pyplaypen-sandbox

No dependencies, required or optional.

from pyplaypen_sandbox import run

result = await run("1 + 1", artifact_root="./artifacts")
# {"status": "ok", "return_value": 2, ...}

Command line

Installing also puts a pyplaypen executable on PATH. Prefix any command with it to run that command under enforced limits, with no code to write.

pyplaypen run --limit wall_seconds=30 -- python script.py

It refuses a limit this machine cannot enforce, and pyplaypen enforcement prints what each limit enforces here.

Extending it

Nothing about numpy, pandas, httpx, or any other library is built in. Code that needs to call out to something gets a globals_provider, an import path to a plain function whose returned dict becomes names in the exec namespace. A return value this library cannot serialize gets a type_projector, an import path of the same form. Both run inside the child, under the same rlimits as the code. projectors.py ships a numpy and pandas projector as the worked example.

Lower-level building blocks

Sandbox.run_process(argv, cwd=...) runs an existing program under the same rlimits, UID drop, process-group teardown and subreaper reaping as execute(). There is no JSON protocol. You get an exit code and bounded stdout and stderr. argv accepts a script, a shell command, or a compiled binary. It runs the target in a cwd you own and changes nothing about that directory. pyplaypen_sandbox.privilege holds the functions both are built from: the rlimits, the UID drop, and Landlock write confinement. It depends on no other part of this package, and not on asyncio, so a plain subprocess.Popen(preexec_fn=...) can call it.

For coding agents

This repo is meant to be adapted to what a project needs.

Set up a process sandbox in this project using
https://github.com/lkraider/pyplaypen-sandbox. Read the README fully
first, then decide the integration this project needs.