Runtime

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 build are 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 login

See also running untrusted LLM code, grading student code and how to run C++ code in a sandbox.

Sources

Checked 25 September 2026.

Facts on this page were checked on 25 September 2026.