Runtime

How to run untrusted Python code safely

Run it in a throwaway Linux microVM with its own kernel, the internet off, a command timeout and a lease that ends on its own.

On Runtime, Python is already there and the first result comes back in about a third of a second. Every sandbox is a Firecracker microVM with Python 3.12, pip, uv, NumPy, pandas and matplotlib in the image. A new sandbox ran its first Python command 351 ms after the create request at the median (p95 815 ms, 20 runs, 24 September 2026, speed). A 2 vCPU, 4 GiB sandbox costs $0.03125 an hour while the code waits and $0.08 with both CPUs busy (pricing).

Run a Python file from your program

Write the code into the sandbox, then run it with an array, so no shell ever parses it:

TypeScriptimport { Sandbox } from "withruntime";const code = "import sys\nprint(sys.version)\nprint(sum(range(100)))";await using sbx = await Sandbox.create({  network: { internet: false },  timeoutSeconds: 300,  onLeaseEnd: "stop",});await sbx.files.write("/workspace/job.py", code);const run = await sbx.exec(["python3", "job.py"], { timeoutMs: 30_000 });console.log(run.exitCode, run.timedOut, run.stdout, run.stderr);
Pythonfrom withruntime import Sandboxcode = "import sys\nprint(sys.version)\nprint(sum(range(100)))"with Sandbox.create(    network={"internet": False},    timeout_seconds=300,    on_lease_end="stop",) as sbx:    sbx.files.write("/workspace/job.py", code)    run = sbx.exec(["python3", "job.py"], timeout_ms=30_000)    print(run.exit_code, run.timed_out, run.stdout, run.stderr)
  • A timeout is a result, not an exception: timedOut is true and you get the output so far. The default is 60 seconds, the maximum 24 hours.
  • A result holds at most 64 KiB of stdout and 64 KiB of stderr. Longer output streams through onStdout (on_stdout) or goes to a file you read back.
  • The sandbox stops when the block ends, even after an error.

What Python has in the image

What Version or detail
Operating system Ubuntu 24.04.5 LTS (noble), amd64, 6.1 kernel
Python 3.12, as python3 and python, with pip, pip3, venv
uv 0.12.17 (uv, uvx)
Data tools NumPy 1.26.4, pandas 2.1.4, matplotlib 3.6.3
C toolchain gcc, g++, make, for packages that build from source
User runtime (uid 1000), home /workspace, sudo works

pip install works without a virtual environment. As the sandbox user it installs to /workspace/.local, whose bin is first on PATH, and the image's pip settings let it past the Ubuntu rule against installing into the system Python (PEP 668). Use python3 -m venv or uv when you want isolation (the sandbox environment).

Install packages, then cut the network

Open the network only to the package index, install, and switch it off before the untrusted code runs. A rule applies at once, to open connections too.

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({  network: { internet: true, allow: ["pypi.org", "*.pythonhosted.org"] },  timeoutSeconds: 600,  onLeaseEnd: "stop",});await sbx.exec("pip install scikit-learn", { check: true, timeoutMs: 300_000 });await sbx.network.set({ internet: false });await sbx.files.write("/workspace/model.py", "import sklearn\nprint(sklearn.__version__)");const run = await sbx.exec(["python3", "model.py"], { timeoutMs: 60_000 });console.log(run.stdout);
Pythonfrom withruntime import Sandboxwith Sandbox.create(    network={"internet": True, "allow": ["pypi.org", "*.pythonhosted.org"]},    timeout_seconds=600,    on_lease_end="stop",) as sbx:    sbx.exec("pip install scikit-learn", check=True, timeout_ms=300_000)    sbx.network.set(internet=False)    sbx.files.write("/workspace/model.py", "import sklearn\nprint(sklearn.__version__)")    print(sbx.exec(["python3", "model.py"], timeout_ms=60_000).stdout)

Give installs a timeoutMs above the 60-second default.

Another Python version

The image ships 3.12. uv installs other versions from the python-build-standalone project and runs a script on one (uv). This needs the internet on:

Terminaluv python install 3.13uv run --python 3.13 job.pyuv run --with rich job.py

Keep variables between runs

A chat assistant or a data agent usually wants a notebook, not a fresh process per answer. The code interpreter keeps Python state between cells and returns matplotlib charts as PNG and pandas data frames as tables (code interpreter):

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ network: { internet: false } });await sbx.interpreter.run("import pandas as pd\ndf = pd.DataFrame({'a': [1, 2, 3]})");const cell = await sbx.interpreter.run("df['a'].sum()");console.log(cell.results[0]?.data["text/plain"]); // 6
Pythonfrom withruntime import Sandboxwith Sandbox.create(network={"internet": False}) as sbx:    sbx.interpreter.run("import pandas as pd\ndf = pd.DataFrame({'a': [1, 2, 3]})")    cell = sbx.interpreter.run("df['a'].sum()")    print(cell["results"][0]["data"]["text/plain"])  # 6

Python is the interpreter's default language and is in the image, so a cell needs no install and no network.

Start every sandbox with your packages

Build a custom image once and every sandbox made from it starts with the packages installed. Building is free; a stored image is charged on its size, and the free trial stores its first three free.

TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.images.build({  name: "py-ml",  recipe: { pip: ["scikit-learn", "polars"] },});await using sbx = await runtime.sandboxes.create({ image: "py-ml", network: { internet: false } });console.log((await sbx.exec(["python3", "-c", "import polars; print(polars.__version__)"])).stdout);
Pythonfrom withruntime import Runtimeruntime = Runtime()runtime.images.build(name="py-ml", recipe={"pip": ["scikit-learn", "polars"]})with runtime.sandboxes.create(image="py-ml", network={"internet": False}) as sbx:    print(sbx.exec(["python3", "-c", "import polars; print(polars.__version__)"]).stdout)

Why not exec() or a subprocess on your server?

Code run with exec() or a subprocess runs as your server, with its files, memory, network and credentials. A container shares your host's kernel. A microVM gives the code its own kernel behind hardware virtualization, and on Runtime root inside it still cannot change the network rules, CPU, memory or cost, which the host enforces (security). For the whole threat list, see running untrusted LLM code.

New accounts get 50 free sandbox hours, no card:

Terminalnpx withruntime sandbox run --trial -- python3 -c 'import pandas; print(pandas.__version__)'

Sources

Facts on this page were checked on 25 September 2026.