UNTRUSTED CODE EXECUTION

Run untrusted code safely.

Spin up an isolated sandbox per run, cap its vCPU, memory, storage, and wall-clock timeout at create, then exec the code with a per-command limit. Read exit_code and logs, and the box is destroyed — no host access, no leftovers.

Each run gets its own kernel, filesystem, and network — the same microVM isolation model AWS Lambda uses. No card required.

run-untrusted.py
$ pip install pilldrops

from pilldrops import Sandbox

# capped, isolated microVM — torn down on exit
with Sandbox.create(
    template="python-3.11",
    vcpu=1, memory_mb=512, timeout=30,
) as sb:
    r = sb.run("python /untrusted.py", timeout=10)
    print(r.exit_code)   # 0
    print(r.stdout)      # hello from a locked-down box
# sandbox destroyed — no host, nothing left behind
microVM
isolation per run
4 caps
vCPU · memory · storage · timeout
per-cmd
exec timeouts, server-enforced
auto
teardown on exit
$5
free credits, no card
[01] — Threat model / what actually contains the code

Isolation, not a chroot.

Untrusted code assumes it can escape. PillDrops runs every execution inside a real microVM — a hardware-virtualized boundary, not a shared-kernel container trick — so a compromise stays inside a throwaway machine.

⬢

Dedicated microVM per run

Each sandbox is a lightweight KVM virtual machine with a hardware-enforced boundary — the same isolation primitive behind AWS Lambda and Fargate, not a container.

◱

Own kernel, filesystem, network

The guest boots its own Linux kernel with a private root filesystem and network namespace. Code can chew up its own box; it cannot reach into another tenant's.

⛒

No host access

There is no shared filesystem mount, no host process table, no privileged socket. The microVM sees only the resources you provisioned for it.

⏛

Server-enforced plan limits

vCPU, memory, storage, session length, and concurrency are enforced on the server — a malicious payload cannot argue its way past the caps you set.

[02] — Cap everything at create / then a per-command timeout

Set the ceiling before the code runs.

Provision the box with hard limits on vcpu, memory_mb, storage_mb, and a wall-clock timeout. Then run the untrusted command with its own timeout so a hang or fork-bomb dies fast instead of billing forever.

capped-exec
from pilldrops import Sandbox

sb = Sandbox.create(
    template="python-3.11",
    vcpu=1,           # hard vCPU cap
    memory_mb=512,     # hard RAM cap
    storage_mb=1024,   # disk cap
    timeout=60,        # whole box dies after 60s
)
r = sb.run("python /user.py", timeout=10)  # per-command kill
print(r.exit_code, r.stdout, r.stderr)
sb.kill()   # destroy now (or let the box expire)
# create a capped sandbox
$ curl -s https://pilldrops.com/v1/sandboxes \
    -H "Authorization: Bearer $PILLDROPS_API_KEY" \
    -d '{"template":"python-3.11","vcpu":1,"memory_mb":512,"storage_mb":1024,"timeout":60}'
# -> {"id":"sb_abc","status":"running","expires_at":"..."}

# exec untrusted code with a per-command timeout
$ curl -s https://pilldrops.com/v1/sandboxes/sb_abc/exec \
    -H "Authorization: Bearer $PILLDROPS_API_KEY" \
    -d '{"cmd":"python /user.py","timeout":10}'
# -> {"stdout":"...","stderr":"...","exit_code":0,"truncated":false}

# destroy it
$ curl -s -X DELETE https://pilldrops.com/v1/sandboxes/sb_abc \
    -H "Authorization: Bearer $PILLDROPS_API_KEY"
[03] — Why it's safe / and cleans up after itself

Isolated, capped, then gone.

The guarantees you need to hand a stranger's script — or your agent's freshly generated code — to a real interpreter without risking your infrastructure.

  • Strong isolation. On KVM nodes a microVM boundary sits between untrusted code and everything else, with no kernel shared with the host or other tenants. Docker nodes use an isolated container, a weaker boundary.
  • Hard resource caps. vcpu, memory_mb, and storage_mb are provisioned once and enforced server-side; runaway code hits the ceiling, not your bill.
  • Two layers of timeout. A per-command timeout kills a hung exec, and the box-level timeout caps total lifetime — nothing runs past 24h.
  • Auto-teardown. Leave the with block, call sb.kill(), or let the box expire — the microVM and its disk are destroyed, so nothing persists between runs.
  • No card to start. $5 in free credits covers thousands of short executions while you validate the model. Full untrusted-code guide →
[04] — People also ask / untrusted code, answered

Common questions

How do you run untrusted code safely?

Execute it inside a disposable, isolated sandbox instead of on your host or in a shared-kernel container. Cap the vCPU, memory, storage, and timeout at create, run each command with its own timeout, capture exit_code and logs, then destroy the box. PillDrops does this per run via one Sandbox.create() call or a single REST POST /v1/sandboxes.

What's the best sandbox to run user code?

One that gives each execution its own kernel, filesystem, and network with server-enforced resource limits — not a language-level sandbox that can be escaped. PillDrops runs isolated Linux machines (the isolation model behind AWS Lambda) and exposes them through a Python/TypeScript SDK, a REST API, a CLI, and a hosted MCP server.

Can you isolate untrusted Python?

Yes. Launch the python-3.11 template, upload the script, and run it with a per-command timeout. Because the interpreter lives inside a microVM with capped CPU, RAM, and disk, even os.system, native extensions, or infinite loops stay contained and are cleaned up on teardown.

How do I execute AI-generated code securely?

Never run model output on your own machine. Pipe it into a fresh sandbox per invocation, read back stdout/stderr and exit_code, and let the box auto-teardown. The hosted MCP server exposes create_sandbox, run_command, and destroy_sandbox so agents can do this directly.

SHIP IT

Run untrusted code without trusting it.

Capped, isolated Linux machines, per-command timeouts, and auto-teardown — via SDK, REST, CLI, or MCP. Start on $5 free credits, no card.