Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CI tests

A lightweight library to run untrusted Python code

Pybox

Pybox is a lightweight Python library for running untrusted Python code. It tries to offer a reasonable tradeoff between security and user-friendliness.

The untrusted code is executed in a protected Docker sandbox with (most) side-effects disabled. All I/O is passed as JSON via the standard input, standard output and standard error.

Main features:

  • ✅ Protected Docker sandbox, offering protection against:
    • code escape attempts
    • fork bombs (pids_limit)
    • memory abuse
    • file system writes
    • network exfiltration (optional)
  • ✅ Optional gVisor integration for enhanced security (highly recommended)
  • ✅ Optional fast mode with container pool (faster but less secure)
  • ✅ Provides both a Python and a FastAPI interface

Pybox is designed so you can switch between a safe and fast mode:

Mode Behavior Security Performance
safe (default) destroy container after each run ⭐⭐⭐⭐⭐ slower
fast reuse warm containers ⭐⭐⭐ much faster

Install

Install Pybox with:

pip install -e .
docker build -t pybox:latest pybox/docker/

Optionally, follow these instructions to install [gVisor] for enhanced security against kernel exploits.

Running untrusted code from Python

from pybox import Executor, Config, Payload


cfg = Config(timeout=3.0)
executor = Executor(cfg)

code = "result = x + y"
input = {"x": 2, "y": 3}
payload = executor.run(code, input)

print(payload)
# Payload(status='ok', result=5, errmsg=None, returncode=0, duration=0.5, resources=None)

assert payload.status == 'ok'
assert payload.result == 5.0
assert payload.returncode == 0

Pybox includes also a convenient execute() function:

from pybox import ExecuteError, execute

code = """
import math
result = math.hypot(x, y)
"""
input = {"x": 3, "y": 4}
result = execute(code, input, config={"timeout": 3.0})

assert result == 5.0

To save raw output to files, set stdout_file and stderr_file in Config:

from pybox import Executor, Config

cfg = Config(
    timeout=3.0,
    stdout_file=".pybox/stdout.txt",
    stderr_file=".pybox/stderr.txt",
)
executor = Executor(cfg)
payload = executor.run("result = x + y", {"x": 2, "y": 3})

assert payload.result == 5.0

The files are written on each run, so they work well in a gitignored folder.

Using the FastAPI service

Start the service:

uvicorn pybox.api:app --reload

Send a request:

curl -X POST http://localhost:8000/run \
  -H "Content-Type: application/json" \
  -d '{"code": "result = x + y", "input": {"x": 2, "y": 3}}'

It should return a JSON response with the full execution payload:

{
  "status": "ok",
  "result": 5,
  "errmsg": null,
  "returncode": 0,
  "duration": 0.123,
  "resources": null
}

Documentation

Pybox uses MkDocs for its documentation.

To install the documentation dependencies:

pip install -e ".[docs]"

Previewing Locally: Run the following command to spin up a local live-reloading server:

mkdocs serve

Then, open your browser to http://127.0.0.1:8000.

Building Static HTML: To generate the static HTML files for hosting (e.g., on GitHub Pages):

mkdocs build

Testing

To run the standard test suite and test the documentation code blocks, ensure you have the dev dependencies installed:

pip install -e ".[dev]"

Run standard tests:

pytest

Run the documentation tests against the README.md to ensure the code examples are valid:

pytest --codeblocks README.md

About

Run untrusted python code in a sandbox

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages