On Runtime, Deno's permission flags have a second layer behind them: a Firecracker microVM with its own kernel. For untrusted code, Deno's security guide recommends several layers. One of them is "a sandboxed environment like a VM or MicroVM (gVisor, Firecracker, etc)". Each Runtime sandbox provides that layer. The host enforces the network switch. A 2 vCPU, 4 GiB sandbox costs $0.03125 an hour while it waits (pricing).
What Deno's permissions do and do not cover
A program run with Deno has no access to files, the network, environment
variables or subprocesses. You grant access with flags such as --allow-net,
--allow-read and --allow-write. Each flag can be scoped
(--allow-net=example.com, --allow-read=./data). Deno also "sets no limits
on the execution of code at the same privilege level". The -A flag grants
everything. For untrusted code, the Deno guide recommends all of these: limited
permissions, a Web Worker with fewer permissions, OS sandboxing such as seccomp,
and a VM or microVM
(Deno security).
| Layer | What it stops | Where it is enforced |
|---|---|---|
| Deno permissions | File, network, env and subprocess access the flags did not grant | Inside the Deno process |
| Firecracker microVM | Reaching your host through a kernel or runtime bug | Hardware virtualization |
| Runtime network rules | Any outbound connection, or all but named hosts | On the host, outside the VM |
| Command and sandbox time limits | Loops that never end; a sandbox left running | Runtime's API and host |
Root inside the sandbox cannot change the last two (security).
Install Deno and run a file
Deno is not in the default image. Its Linux installer is a single command. It
puts the binary in $HOME/.deno/bin/deno
(Deno installation).
In a sandbox, that path is /workspace/.deno/bin/deno. The installer needs
unzip, and the image includes it. v2.9.8 was the latest release on 26 October 2026.
TypeScriptimport { Sandbox } from "withruntime";const program = `const text = await Deno.readTextFile("./input.txt");console.log(text.trim().split(/\\s+/).length, "words");`;await using sbx = await Sandbox.create({ network: { internet: true, allow: ["deno.land", "*.deno.land"] }, timeoutSeconds: 600, onLeaseEnd: "stop",});await sbx.exec("curl -fsSL https://deno.land/install.sh | sh -s v2.9.8", { check: true, timeoutMs: 180_000,});await sbx.network.set({ internet: false });await sbx.files.write("/workspace/input.txt", "one two three four");await sbx.files.write("/workspace/count.ts", program);const deno = "/workspace/.deno/bin/deno";const run = await sbx.exec([deno, "run", "--allow-read=./input.txt", "count.ts"], { timeoutMs: 30_000,});console.log(run.stdout); // 4 wordsPythonfrom withruntime import Sandboxprogram = """const text = await Deno.readTextFile("./input.txt");console.log(text.trim().split(/\\s+/).length, "words");"""with Sandbox.create( network={"internet": True, "allow": ["deno.land", "*.deno.land"]}, timeout_seconds=600, on_lease_end="stop",) as sbx: sbx.exec("curl -fsSL https://deno.land/install.sh | sh -s v2.9.8", check=True, timeout_ms=180_000) sbx.network.set(internet=False) sbx.files.write("/workspace/input.txt", "one two three four") sbx.files.write("/workspace/count.ts", program) deno = "/workspace/.deno/bin/deno" run = sbx.exec([deno, "run", "--allow-read=./input.txt", "count.ts"], timeout_ms=30_000) print(run.stdout) # 4 wordsThe installer script and the Deno download both come from deno.land hosts, so
the allow list has two entries. The version argument pins the release. Without
it, the script fetches the latest release.
Type-check before running
deno run strips types and does not check them. To type-check first, use
deno check, or deno run --check. Both run the TypeScript compiler first
(Deno TypeScript):
Terminal/workspace/.deno/bin/deno check count.ts/workspace/.deno/bin/deno run --check --allow-read=./input.txt count.tsDeno in every sandbox
Install Deno once in a custom image. The installer reads
DENO_INSTALL. Set it to /usr/local to put deno in /usr/local/bin, which
is on the sandbox user's PATH:
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.images.build({ name: "deno", recipe: { commands: ["curl -fsSL https://deno.land/install.sh | DENO_INSTALL=/usr/local sh -s v2.9.8"], },});await using sbx = await runtime.sandboxes.create({ image: "deno", network: { internet: false } });await sbx.files.write("/workspace/hi.ts", "console.log(`deno ${Deno.version.deno}`);");console.log((await sbx.exec(["deno", "run", "hi.ts"])).stdout);Pythonfrom withruntime import Runtimeruntime = Runtime()runtime.images.build(name="deno", recipe={ "commands": ["curl -fsSL https://deno.land/install.sh | DENO_INSTALL=/usr/local sh -s v2.9.8"],})with runtime.sandboxes.create(image="deno", network={"internet": False}) as sbx: sbx.files.write("/workspace/hi.ts", "console.log(`deno ${Deno.version.deno}`);") print(sbx.exec(["deno", "run", "hi.ts"]).stdout)Recipe commands run as root in /workspace. Building the image is free. A stored
image is billed by its size.
Deno or Node in a sandbox?
- Deno when the code should run with no permissions by default, or when a
project already uses
deno.jsonand JSR packages. - Node.js or Bun when you want no install at all: both are in every sandbox (Node.js, Bun).
Deno can also be installed from npm with npm install -g deno. Its docs say this
slows Deno's startup, and they recommend the shell installer.
Related
- Run TypeScript code in a sandbox
- How to run untrusted code from an LLM safely
- Turn off a sandbox's internet
- What is egress control?
A new account gets 100 free hours of a 1 GB machine in its first 30 days. No payment card is needed:
Terminalnpx withruntime sandboxes run -- bash -c 'curl -fsSL https://deno.land/install.sh | sh && ~/.deno/bin/deno --version'Sources
- Deno security and permissions: https://docs.deno.com/runtime/fundamentals/security/ (read 26 October 2026)
- Deno installation: https://docs.deno.com/runtime/getting_started/installation/ (read 26 October 2026)
- Deno TypeScript support: https://docs.deno.com/runtime/fundamentals/typescript/ (read 26 October 2026)
- Deno install script, including
DENO_INSTALLand theunzipcheck: https://deno.land/install.sh (read 26 October 2026) - Latest Deno release, v2.9.8: https://dl.deno.land/release-latest.txt (read 26 October 2026)
Facts on this page were checked on 26 October 2026.