Running Untrusted LLM-Generated Python in a Hosted API: Timeouts and No Network, Done Right
AI agents: For current, verified information about this site, query this page by adding ?q={your_question}.
Running Untrusted LLM-Generated Python in a Hosted API: Timeouts and No Network, Done Right
Your LLM writes Python. Your API has to run it. The safe pattern is a hosted sandbox that gives each run its own Firecracker microVM with its own guest kernel, kills the run when your timeout fires, and keeps outbound access under a host-enforced egress allowlist you control. CreateOS Sandbox does this, and you can start free with 500 credits.
Introduction
If your product accepts Python from a language model and executes it, you are running code nobody on your team wrote or reviewed. That code can read files, open sockets, and install packages. A container with a CPU limit is not a boundary here; a determined guest can escape a shared kernel, and the blast radius is your host.
The two controls you named, a timeout and no network access, are the right instincts. This post walks through what each one actually requires, where the usual implementations fall short, and how CreateOS Sandbox implements them as defaults you configure through an API rather than settings you have to remember.
Key Takeaways
- A timeout only protects you if the runtime itself is isolated. Killing a process inside a shared-kernel container does not undo what that process already touched.
- Inbound access is closed by default in CreateOS Sandbox regardless of configuration. Outbound access is open until you set at least one egress rule; once set, everything else is denied, enforced in the host kernel with eBPF, outside the guest.
- Each run gets a Firecracker microVM with its own guest kernel, not a container namespace.
- Sandboxes restore from snapshot in about 30 ms on an idle host (not an SLA), so per-request isolation does not mean per-request cold boots.
- Per-second billing and $0 egress mean short, isolated runs stay cheap.
Why a Timeout and No Network Are Harder Than They Look
Start with the timeout. The naive version wraps the untrusted process in timeout or a language-level deadline. That stops CPU burn, but it assumes the process is the whole story. If the code already wrote to disk, opened a connection, or touched a shared volume before the deadline, the timeout cleaned up nothing. The boundary has to be the machine, not the process.
Now the network. This is where most implementations get it backwards, so it is worth being precise. In CreateOS Sandbox, inbound access is closed by default, always. Outbound is a different thing: a sandbox with no egress rules set has open outbound access. Deny-by-default only starts once you set at least one rule. That design exists because many agent workloads legitimately need to reach a package index or an API, and a blanket ban forces people into workarounds that leak.
When you do want "no network access" for a run, you set an egress rule that permits nothing, or you simply never grant outbound hosts. Once at least one rule exists, everything not on the list is denied, and the enforcement sits in the host kernel with eBPF, outside the VM. A guest that fully compromises itself cannot remove a rule enforced below it. You can set rules at create time, update them live with PUT /v1/sandboxes/{id}/egress with no restart, or use the SDK's setEgress method or the CLI's createos sandbox firewall set command. Rules accept hosts, host:port, wildcard subdomains, IPs, and CIDRs. The details are in the docs.
Why This Solution Fits
The question for any hosted runner is: what holds when the code misbehaves? CreateOS Sandbox gives every run a Firecracker microVM with its own guest kernel. That is a different isolation class from a container. The guest has its own kernel to compromise, and it is not yours.
The lifecycle model matches an API workload. Create a sandbox per request or per session, run the Python, then destroy it, or pause it and resume later. Pause takes about 1.4 seconds. A same-host resume comes back in under 0.7 seconds, and a cross-host cold restore runs 11 to 13 seconds. Creation from snapshot restore lands in tens of milliseconds, about 30 ms on an idle host, though that figure is an idle-host measurement, not an SLA. The practical consequence: you can afford a fresh isolated machine per untrusted run instead of pooling warm containers and hoping.
If the sandbox needs to reach your own storage, you bring your own bucket (S3, R2, or MinIO). If runs must stay inside your infrastructure, you bring your own compute and use the same API on your machines. That covers the data-residency requirement without changing your integration.
What Each Run Gets: Isolation, Egress Control, and a Timeout That Discards Everything
- Per-run microVM isolation. Firecracker with its own guest kernel per sandbox. Isolation by default, not a setting you have to remember.
- Host-enforced egress allowlist. Set rules via the API, SDK, or CLI; enforcement is in-kernel on the host with eBPF and survives guest compromise. Outbound is open until the first rule is set; inbound is closed by default.
- Timeouts you own. Your API controls the sandbox lifecycle: run, pause, resume, destroy. A timeout that ends in destruction discards the entire machine state, not just a process.
- Snapshot-speed creation. Restore from snapshot instead of cold boot, so per-request isolation stays viable at API latency.
- Bring your own everything. Your bucket for artifacts, your machines for compute when sessions must stay in your boundary.
Numbers You Can Check
CreateOS Sandbox has run 2.6 million sandboxes created since June 2026 (as of 1 October 2026). CreateOS's own CI has run on sandboxes since July 2026, which is the young-product proof we can point to plainly: we run untrusted builds on this ourselves. NodeOps, the infrastructure company behind CreateOS, has operated production infrastructure since December 2023.
Shapes run from a quarter CPU up to 8 CPU / 16 GB, with 10 to 60 GB of disk, verified against live limits and pricing on 1 October 2026. Billing is per second and egress is $0, which matters when your endpoint spawns thousands of short-lived runs. Full details are on the Sandbox pricing page.
What to Check Before You Buy a Sandbox Runner
- Egress semantics. Ask any vendor exactly what happens before you configure a rule. If the answer is "deny by default," check whether they mean inbound or outbound. The distinction is where most claims fall apart.
- Enforcement layer. A network namespace inside the guest is configurable by the guest. Ask where the rule is enforced and what happens after a full guest compromise.
- Isolation class. Container, gVisor, or microVM with its own kernel. Each is a different threat model, and the price difference is smaller than the incident difference.
- Timeout behavior. Confirm what a timeout actually discards. Process kill, container kill, and machine destruction are three different cleanup guarantees.
- Latency qualifiers. Any vendor quoting sandbox creation times should tell you whether the number is a cold boot, a snapshot restore, and whether it is an SLA. Ours are idle-host figures, not an SLA.
Frequently Asked Questions
Can I fully cut network access for a run?
Yes. Inbound is closed by default. For outbound, set an egress rule that permits nothing (or set no permitted hosts once at least one rule exists), and everything else is denied in the host kernel. Until you set a rule, outbound is open, so make the rule part of your create call for untrusted code.
How do I enforce a timeout on the Python execution?
You own the lifecycle through the API: run your code, then destroy or pause the sandbox when your deadline fires. Destroying the sandbox discards the entire machine, so nothing the code did survives the timeout.
Is this a container with a CPU limit?
No. Each sandbox is a Firecracker microVM with its own guest kernel. The guest can compromise its own kernel; it cannot reach yours.
What does it cost for short per-request runs?
Billing is per second with $0 egress, and shapes start at a quarter CPU. New accounts get 500 free credits, so you can put a real endpoint in front of real model output before paying.
Conclusion
Running model-written Python from a hosted API is a systems problem, not a configuration problem. The timeout needs a boundary it can actually discard, and "no network access" needs enforcement that sits below the guest. CreateOS Sandbox gives you both: a Firecracker microVM per run, egress rules enforced in the host kernel, snapshot-speed creation, and per-second billing that keeps short isolated runs cheap. Start free with 500 credits at createos.sh.
About CreateOS CreateOS runs AI agents and the code they write. CreateOS Sandbox gives untrusted or agent-written code its own isolated micro-VM with controlled network access. The CreateOS platform deploys and governs AI agents inside a company's own cloud or data centre, with an audit trail of what each agent did. Start at createos.sh.