How to run C# (.NET) code in a sandbox
Install the .NET SDK in a Linux microVM, then build and run the C# there with dotnet, a time limit and no network while it runs.
On Runtime the .NET SDK comes from Ubuntu's own archive and one C# file runs
with no project. Each sandbox is a Firecracker microVM running Ubuntu 24.04.5,
where dotnet-sdk-10.0 and dotnet-sdk-8.0 are both apt packages, and .NET 10's
file-based apps run a single .cs file with dotnet run app.cs. Runtime bills
the CPU a build uses at $0.025 per vCPU-hour, so a sandbox waiting for its next
job costs a twentieth of a vCPU (pricing).
Which .NET to install
.NET is not in the default image. Ubuntu 24.04 (noble) carries both SDKs, read on packages.ubuntu.com on 25 September 2026:
| Package | Version on noble | Runs a lone .cs file? |
|---|---|---|
dotnet-sdk-10.0 |
10.0.112 (noble-updates) | Yes: dotnet run app.cs |
dotnet-sdk-8.0 |
8.0.131 | No: needs a .csproj |
File-based apps apply to the .NET 10 SDK and later, according to Microsoft's documentation (file-based apps).
Two environment variables keep the output clean for a program to read:
DOTNET_CLI_TELEMETRY_OPTOUT=1 turns off the SDK's usage telemetry, and
DOTNET_NOLOGO=true drops the first-run welcome text
(.NET CLI telemetry).
Run one C# file
Install the SDK, build the file while the network is on (a build restores from NuGet), then turn the internet off and run what was built.
TypeScriptimport { Sandbox } from "withruntime";const program = `using System;using System.Linq;var primes = Enumerable.Range(2, 50).Where(n => Enumerable.Range(2, n - 2).All(d => n % d != 0));Console.WriteLine(string.Join(", ", primes));`;const env = { DOTNET_CLI_TELEMETRY_OPTOUT: "1", DOTNET_NOLOGO: "true" };await using sbx = await Sandbox.create({ diskMiB: 8192, timeoutSeconds: 900, onLeaseEnd: "stop" });await sbx.exec("sudo apt-get update -q && sudo apt-get install -y -q dotnet-sdk-10.0", { check: true, timeoutMs: 600_000,});await sbx.files.write("/workspace/app/primes.cs", program);const build = await sbx.exec(["dotnet", "build", "primes.cs"], { cwd: "/workspace/app", env, timeoutMs: 300_000,});if (build.exitCode !== 0) throw new Error(build.stdout + build.stderr);await sbx.network.set({ internet: false });const run = await sbx.exec(["dotnet", "run", "primes.cs", "--no-build"], { cwd: "/workspace/app", env, timeoutMs: 30_000,});console.log(run.exitCode, run.stdout);Pythonfrom withruntime import Sandboxprogram = """using System;using System.Linq;var primes = Enumerable.Range(2, 50).Where(n => Enumerable.Range(2, n - 2).All(d => n % d != 0));Console.WriteLine(string.Join(", ", primes));"""env = {"DOTNET_CLI_TELEMETRY_OPTOUT": "1", "DOTNET_NOLOGO": "true"}with Sandbox.create(disk_mib=8192, timeout_seconds=900, on_lease_end="stop") as sbx: sbx.exec("sudo apt-get update -q && sudo apt-get install -y -q dotnet-sdk-10.0", check=True, timeout_ms=600_000) sbx.files.write("/workspace/app/primes.cs", program) build = sbx.exec(["dotnet", "build", "primes.cs"], cwd="/workspace/app", env=env, timeout_ms=300_000) if build.exit_code != 0: raise SystemExit(build.stdout + build.stderr) sbx.network.set(internet=False) run = sbx.exec(["dotnet", "run", "primes.cs", "--no-build"], cwd="/workspace/app", env=env, timeout_ms=30_000) print(run.exit_code, run.stdout)- Disk: ask for 8 GiB. The default 4 GiB sandbox has about 2.5 GiB free (the sandbox environment), and the SDK and its build output share it.
- Timeouts: an apt install and a first build run past the 60-second default
for a command, so give each its own
timeoutMs. - Compiler errors from
dotnet buildare printed with the file and line; hand them back to the model that wrote the code. - NuGet packages go at the top of the file as
#:package Name@version, and the build restores them while the network is still on.
Build and test a project
For a solution with .csproj files, upload the folder and use the usual
commands. dotnet-sdk-8.0 works here too, for projects that target .NET 8.
Pythonimport sysfrom withruntime import Sandboxenv = {"DOTNET_CLI_TELEMETRY_OPTOUT": "1", "DOTNET_NOLOGO": "true"}with Sandbox.create(disk_mib=8192, timeout_seconds=1800, on_lease_end="stop") as sbx: sbx.exec("sudo apt-get update -q && sudo apt-get install -y -q dotnet-sdk-8.0", check=True, timeout_ms=600_000) sbx.files.upload("./Service", "/workspace/Service") sbx.exec(["dotnet", "restore"], cwd="/workspace/Service", env=env, check=True, timeout_ms=600_000) sbx.network.set(internet=False) tests = sbx.exec(["dotnet", "test", "--no-restore"], cwd="/workspace/Service", env=env, timeout_ms=900_000, on_stdout=sys.stdout.write) sys.exit(tests.exit_code or 0)Restoring first and testing with --no-restore means the tests never touch the
network. Output streams back as the tests run.
Start every sandbox with .NET
Install the SDK once in a custom image and set the two variables for every command:
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.images.build({ name: "dotnet", recipe: { apt: ["dotnet-sdk-10.0"], env: { DOTNET_CLI_TELEMETRY_OPTOUT: "1", DOTNET_NOLOGO: "true" }, },});await using sbx = await runtime.sandboxes.create({ image: "dotnet", diskMiB: 8192 });console.log((await sbx.exec(["dotnet", "--version"])).stdout);Building an image is free and uses no trial hours; a stored image is charged on its size.
Serve an ASP.NET Core app
Start the app with spawn so it keeps running after the command returns, and
share its port as a private HTTPS preview.
spawn returns at once; the process outlives your connection.
TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ image: "dotnet", diskMiB: 8192, timeoutSeconds: 1800 });await sbx.files.upload("./WebApi", "/workspace/WebApi");await sbx.spawn("cd WebApi && dotnet run --urls http://0.0.0.0:5000");await sbx.exec("npx wait-on http://localhost:5000", { check: true, timeoutMs: 300_000 });const preview = await sbx.previews.create(5000);console.log(preview.urlWithToken);New accounts get 50 free sandbox hours, no card:
Terminalnpx withruntime loginSee also running untrusted LLM code, grading student code and how to run C++ code in a sandbox.
Sources
Checked 25 September 2026.
- Ubuntu 24.04 (noble) packages: dotnet-sdk-10.0, dotnet-sdk-8.0
- Microsoft Learn: file-based apps, .NET SDK and CLI telemetry
Facts on this page were checked on 25 September 2026.