How to run Ruby code in a sandbox
Install Ruby from Ubuntu in an isolated Linux microVM, or start from the official Ruby image, then run the file with ruby under a timeout.
On Runtime you choose the Ruby: Ubuntu's 3.2 in one apt command, or
Ruby 4.0 from the official Docker image, built once into a sandbox image.
Every sandbox is a Firecracker microVM with its own kernel and sudo, and
the default image already has gcc and make for gems with C extensions. A
2 vCPU, 4 GiB sandbox costs $0.03125 an hour while it waits and $0.08 with
both CPUs busy (pricing).
Which Ruby to use
| Source | Ruby version on 25 September 2026 | How |
|---|---|---|
Ubuntu 24.04 ruby package (main) |
3.2.3 | sudo apt-get install -y ruby |
Ubuntu 24.04 ruby-full (universe) |
3.2.3, with headers and docs | sudo apt-get install -y ruby-full |
Official ruby image on Docker Hub |
4.0 (tags 4.0.7, 4.0-slim) |
A custom image built from it, below |
| rbenv with ruby-build, or mise | Any release you build | Ruby's recommended version managers |
Ruby's own site lists 4.0.7 and 3.4.11 as the stable releases, gives
sudo apt-get install ruby-full for Ubuntu, and notes that package managers
may install older versions than the latest
(Ruby).
Ruby is not in the default sandbox image and not one of the code
interpreter's languages, so it runs as a file or a script with exec.
Install Ruby and run a file
TypeScriptimport { Sandbox } from "withruntime";const program = `words = ARGV.first.splitcounts = words.tally.sort_by { |_, n| -n }.first(3)puts counts.map { |w, n| "#{w}=#{n}" }.join(" ")`;await using sbx = await Sandbox.create({ timeoutSeconds: 900, onLeaseEnd: "stop" });await sbx.exec("sudo apt-get update -q && sudo apt-get install -y -q ruby", { check: true, timeoutMs: 600_000,});await sbx.network.set({ internet: false }); // the program runs offlineawait sbx.files.write("/workspace/top.rb", program);const run = await sbx.exec(["ruby", "top.rb", "a b a c b a"], { timeoutMs: 30_000 });console.log(run.exitCode, run.stdout); // 0 a=3 b=2 c=1Pythonfrom withruntime import Sandboxprogram = """words = ARGV.first.splitcounts = words.tally.sort_by { |_, n| -n }.first(3)puts counts.map { |w, n| "#{w}=#{n}" }.join(" ")"""with Sandbox.create(timeout_seconds=900, on_lease_end="stop") as sbx: sbx.exec("sudo apt-get update -q && sudo apt-get install -y -q ruby", check=True, timeout_ms=600_000) sbx.network.set(internet=False) # the program runs offline sbx.files.write("/workspace/top.rb", program) run = sbx.exec(["ruby", "top.rb", "a b a c b a"], timeout_ms=30_000) print(run.exit_code, run.stdout) # 0 a=3 b=2 c=1- The text reaches the program as
ARGV.firstexactly as given. An array runsrubywith no shell, so quotes and semicolons in it are just characters. - Errors and backtraces are on
stderr, with a non-zero exit code. - A script that never ends comes back with
timedOut: trueaftertimeoutMsand whatever it printed.
Gems
Install gems while the network is on, then close it before the code you do
not trust runs. The sandbox is yours, so sudo gem install into the system
Ruby is fine:
TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ timeoutSeconds: 1200, onLeaseEnd: "stop" });await sbx.exec("sudo apt-get update -q && sudo apt-get install -y -q ruby-full", { check: true, timeoutMs: 600_000,});await sbx.exec("sudo gem install --no-document rainbow", { check: true, timeoutMs: 300_000 });await sbx.network.set({ internet: false });await sbx.files.write("/workspace/hi.rb", 'require "rainbow"\nputs Rainbow("ok").green');console.log((await sbx.exec(["ruby", "hi.rb"], { timeoutMs: 30_000 })).stdout);ruby-full depends on ruby-dev, the headers that gems with C extensions
build against, with the image's gcc.
A Rails or Bundler project
Upload the project, install the bundle, then run the tests with the network off:
TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ image: "ruby4", diskMiB: 8192, timeoutSeconds: 3600, onLeaseEnd: "stop",});await sbx.files.upload("./my-app", "/workspace/app");await sbx.exec("bundle install", { cwd: "/workspace/app", check: true, timeoutMs: 900_000 });await sbx.network.set({ internet: false });const test = await sbx.exec(["bundle", "exec", "rake", "test"], { cwd: "/workspace/app", timeoutMs: 1_800_000, onStdout: (text) => process.stdout.write(text),});console.log("exit", test.exitCode);This uses the ruby4 image below. A timeoutMs over 60 seconds streams the
output, and the result keeps all of it.
Ruby in every sandbox
A custom image can start from any public image, so the official Ruby image gives every sandbox Ruby 4.0 with no install. Or add Ubuntu's Ruby to Runtime's own base with a recipe:
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.images.build({ name: "ruby4", image: "ruby:4.0-slim" });await runtime.images.build({ name: "ruby32", recipe: { apt: ["ruby-full"] } });await using sbx = await runtime.sandboxes.create({ image: "ruby4", network: { internet: false } });console.log((await sbx.exec(["ruby", "--version"])).stdout);Pythonfrom withruntime import Runtimeruntime = Runtime()runtime.images.build(name="ruby4", image="ruby:4.0-slim")runtime.images.build(name="ruby32", recipe={"apt": ["ruby-full"]})with runtime.sandboxes.create(image="ruby4", network={"internet": False}) as sbx: print(sbx.exec(["ruby", "--version"]).stdout)The recipe image keeps Runtime's base, with Python, Node.js and the usual tools next to Ruby. Building is free; a stored image is charged on its size.
Related
- Run untrusted Python code safely
- Grade student code
- Per-user dev environments
- How to run untrusted code from an LLM safely
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 ruby && ruby --version'Sources
- Ruby installation: https://www.ruby-lang.org/en/documentation/installation/ (read 25 September 2026)
- Ruby downloads, stable 4.0.7 and 3.4.11: https://www.ruby-lang.org/en/downloads/ (read 25 September 2026)
- Docker Hub, official
rubyimage tags4.0.7and4.0-slim: https://hub.docker.com/_/ruby (read 25 September 2026) - Ubuntu 24.04 package indexes (
ruby1:3.2ubuntu1,ubuntu1): http://archive.ubuntu.com/ubuntu/dists/noble-updates/main/binary-amd64/ and http://archive.ubuntu.com/ubuntu/dists/noble/universe/binary-amd64/ (read 25 September 2026)ruby3.23.2.3-1ubuntu0.24.04.8,ruby-full1:3.2
Facts on this page were checked on 25 September 2026.