How to compile and run Rust code in a sandbox
Install Rust with rustup or Ubuntu's rustc and cargo in an isolated microVM, build the code there, and run it with the network off.
On Runtime, untrusted Rust is contained twice over: at build time and at
run time. Cargo compiles a package's build.rs and runs it just before
building the package, so the build runs other people's code and belongs in
the sandbox as much as the binary does. Every Runtime sandbox is a Firecracker microVM with its own
kernel, gcc and sudo, and a 2 vCPU, 4 GiB sandbox costs $0.08 an hour
with both CPUs compiling (pricing).
Which Rust to install
| Source | Package or command | Version on 25 September 2026 |
|---|---|---|
| Ubuntu 24.04 archive (main) | sudo apt-get install -y rustc cargo |
1.75.0 |
| Ubuntu 24.04 archive (universe) | sudo apt-get install -y rustc-1.80 |
1.80.1 |
| rustup, the official installer | the sh.rustup.rs script, below |
1.98.1, the current stable release |
The image has none of these; it has the C toolchain (gcc, g++, make)
that crates with C code build against. Pick rustup when your code or its
crates need a recent compiler.
Install with rustup and run a program
rustup installs rustc, cargo and rustup into ~/.cargo/bin
(Rust); in a sandbox, home is
/workspace. -y skips the prompts and --profile minimal leaves out the
docs (rustup).
TypeScriptimport { Sandbox } from "withruntime";const program = `fn main() { let words = ["sandbox", "microvm", "kernel"]; let longest = words.iter().max_by_key(|w| w.len()).unwrap(); println!("{longest}");}`;await using sbx = await Sandbox.create({ diskMiB: 8192, timeoutSeconds: 1200, onLeaseEnd: "stop" });await sbx.exec( "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal", { check: true, timeoutMs: 600_000 },);await sbx.network.set({ internet: false }); // compile and run offlineawait sbx.files.write("/workspace/job/main.rs", program);const cargoBin = "/workspace/.cargo/bin";const build = await sbx.exec([`${cargoBin}/rustc`, "-O", "main.rs", "-o", "main"], { cwd: "/workspace/job", timeoutMs: 300_000,});if (build.exitCode !== 0) console.error(build.stderr);const run = await sbx.exec(["./main"], { cwd: "/workspace/job", timeoutMs: 10_000 });console.log(run.stdout); // sandboxPythonfrom withruntime import Sandboxprogram = """fn main() { let words = ["sandbox", "microvm", "kernel"]; let longest = words.iter().max_by_key(|w| w.len()).unwrap(); println!("{longest}");}"""with Sandbox.create(disk_mib=8192, timeout_seconds=1200, on_lease_end="stop") as sbx: sbx.exec("curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal", check=True, timeout_ms=600_000) sbx.network.set(internet=False) # compile and run offline sbx.files.write("/workspace/job/main.rs", program) cargo_bin = "/workspace/.cargo/bin" build = sbx.exec([f"{cargo_bin}/rustc", "-O", "main.rs", "-o", "main"], cwd="/workspace/job", timeout_ms=300_000) if build.exit_code != 0: print(build.stderr) run = sbx.exec(["./main"], cwd="/workspace/job", timeout_ms=10_000) print(run.stdout) # sandbox- Disk: the default 4 GiB sandbox had about 2.5 GiB free on 24 September 2026. A toolchain and a
targetfolder add up, so ask for 8 GiB. - Time: give the install and each build a
timeoutMs; the default is 60 seconds. The sandbox's lease (timeoutSeconds) can run up to an hour ahead and be extended. - Errors: compiler errors are on
stderr. Return them to the model that wrote the code as they are.
A Cargo project
Fetch the crates with the internet on, then build and test offline, so
neither build.rs nor the tests can call out:
TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ image: "rust", diskMiB: 8192, timeoutSeconds: 3600, onLeaseEnd: "stop",});await sbx.files.upload("./my-crate", "/workspace/crate");await sbx.exec("cargo fetch", { cwd: "/workspace/crate", check: true, timeoutMs: 600_000 });await sbx.network.set({ internet: false });const test = await sbx.exec(["cargo", "test", "--offline"], { cwd: "/workspace/crate", timeoutMs: 1_800_000, onStdout: (text) => process.stdout.write(text), onStderr: (text) => process.stderr.write(text),});console.log("exit", test.exitCode);Pythonimport sysfrom withruntime import Sandboxwith Sandbox.create(image="rust", disk_mib=8192, timeout_seconds=3600, on_lease_end="stop") as sbx: sbx.files.upload("./my-crate", "/workspace/crate") sbx.exec("cargo fetch", cwd="/workspace/crate", check=True, timeout_ms=600_000) sbx.network.set(internet=False) test = sbx.exec(["cargo", "test", "--offline"], cwd="/workspace/crate", timeout_ms=1_800_000, on_stdout=sys.stdout.write, on_stderr=sys.stderr.write) print("exit", test.exit_code)This uses the rust image below. Both streams print as the build goes.
Rust in every sandbox
Install the toolchain once in a custom image so no sandbox
waits for it. rustup reads RUSTUP_HOME and CARGO_HOME for where to put
things and needs them set whenever the toolchain runs
(rustup); a
recipe's env stays set in every sandbox made from the image. Recipe commands
run as root, so the last command lets the sandbox user write Cargo's cache.
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.images.build({ name: "rust", recipe: { env: { RUSTUP_HOME: "/usr/local/rustup", CARGO_HOME: "/usr/local/cargo" }, commands: [ "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --no-modify-path", "ln -sf /usr/local/cargo/bin/* /usr/local/bin/", "chmod -R a+w /usr/local/rustup /usr/local/cargo", ], },});Pythonfrom withruntime import Runtimeruntime = Runtime()runtime.images.build(name="rust", recipe={ "env": {"RUSTUP_HOME": "/usr/local/rustup", "CARGO_HOME": "/usr/local/cargo"}, "commands": [ "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --no-modify-path", "ln -sf /usr/local/cargo/bin/* /usr/local/bin/", "chmod -R a+w /usr/local/rustup /usr/local/cargo", ],})For Ubuntu's compiler instead, the recipe is { apt: ["rustc", "cargo"] }.
Building an image is free; a stored image is charged on its size.
Many builds at once
Each sandbox is its own machine with its own disk, so parallel builds never
share a target folder or a lock on Cargo's cache. A paid account runs 100
sandboxes at once to start with. New accounts get 50 free sandbox hours, no
card:
Terminalnpx withruntime sandbox run --trial -- bash -c 'sudo apt-get update -q && sudo apt-get install -y -q rustc && rustc --version'Related
- Run Go code in a sandbox
- How to run untrusted code from an LLM safely
- A coding agent's sandbox
- Agent evals and SWE-bench
Sources
- Rust installation: https://rust-lang.org/tools/install/ (read 25 September 2026)
- Cargo build scripts: https://doc.rust-lang.org/cargo/reference/build-scripts.html (read 25 September 2026)
- rustup installation and options: https://rust-lang.github.io/rustup/installation/index.html and https://rust-lang.github.io/rustup/installation/other.html (read 25 September 2026)
- Current stable Rust, rustc 1.98.1: https://static.rust-lang.org/dist/channel-rust-stable.toml (read 25 September 2026)
- Ubuntu 24.04 package indexes (
rustcandcargo1.75.0+dfsg0ubuntu1-0ubuntu7.4,rustc-1.801.80.1+dfsg0ubuntu1-0ubuntu0.24.04.01): http://archive.ubuntu.com/ubuntu/dists/noble-updates/ (read 25 September 2026)
Facts on this page were checked on 25 September 2026.