
Security News
Meet Socket at Black Hat Europe and BSides London 2025
Socket is heading to London! Stop by our booth or schedule a meeting to see what we've been working on.
@deno/sandbox
Advanced tools
> ⚠️ Deno Deploy Sandbox API is currently in private alpha. Interested in trying it out? Email > [deploy@deno.com](mailto:deploy@deno.com).
⚠️ Deno Deploy Sandbox API is currently in private alpha. Interested in trying it out? Email deploy@deno.com.
A TypeScript/JavaScript SDK for creating and interacting with secure, isolated sandbox environments. Create isolated sandboxes to securely run shell scripts, spawn processes, execute JavaScript applications and REPLs, and interact with files remotely.
next dev.# Using Deno
deno add jsr:@deno/sandbox
# Using npm
npm install @deno/sandbox
# Using pnpm
pnpm install jsr:@deno/sandbox
# Using yarn
yarn add jsr:@deno/sandbox
Go to the "Sandbox" tab in the Deno Deploy EA dashboard. At the moment you will only be able to see this if you are invited to the private alpha - email deploy@deno.com to get access.
Create an access token and set it as the DENO_DEPLOY_TOKEN environment variable.
Use the @deno/sandbox SDK to create a new sandbox and interact with it.
import { Sandbox } from "@deno/sandbox";
// Create a new sandbox
await using sandbox = await Sandbox.create();
// Write a TypeScript file
await sandbox.writeTextFile("hello.ts", "console.log('Hello, Sandbox!');");
// Run it
const child = await sandbox.spawn("deno", {
args: ["run", "hello.ts"],
stdout: "piped",
});
// Read the output
for await (const chunk of child.stdout) {
console.log(new TextDecoder().decode(chunk));
}
// Automatically shuts down the sandbox here
View the full API documentation here.
The snippets below assume package.json contains { "type": "module" }, the @deno/sandbox
package is installed, and that DENO_DEPLOY_TOKEN env var is set.
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
const result = await sandbox.eval(`
const a = 1;
const b = 2;
a + b;
`);
console.log("result:", result);
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
// New template literal API (recommended)
const result = await sandbox.sh`whoami`.stdout("piped");
console.log("result:", result.stdout); // → "sandbox\n"
// Or get just the text
const text = await sandbox.sh`pwd`.text();
console.log("result:", text); // → "/home/sandbox\n"
Tip: prefer child.output() for small outputs. For long‑running processes or large output, stream
the stdout/stderr by using child.spawn().
This creates a minimal Express app inside the sandbox, runs it on port 3000, and exposes it publicly
using sandbox.exposeHttp().
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
// 1) Write package.json and server.js in the sandbox
await sandbox.writeTextFile(
"package.json",
JSON.stringify(
{
name: "sandbox-express-demo",
private: true,
type: "module",
dependencies: { express: "^4.19.2" },
},
null,
2,
),
);
await sandbox.writeTextFile(
"server.js",
`import express from 'express';
const app = express();
app.get('/', (req, res) => res.send('Hello from Express in @deno/sandbox!'));
app.get('/time', (req, res) => res.json({ now: new Date().toISOString() }));
app.listen(3000, () => console.log('listening on :3000'));
`,
);
console.log("Installing deps...");
const npm = await sandbox.spawn("deno", {
args: ["install"],
stdout: "piped",
stderr: "piped",
});
const npmOut = await npm.output();
if (!npmOut.status.success) {
throw new Error(npmOut.stderrText ?? "");
}
console.log("Starting server...");
const server = await sandbox.createJsRuntime({
entrypoint: "server.js",
});
// 4) Publish to the internet
const publicUrl = await sandbox.exposeHttp({ port: 3000 });
console.log("Public URL:", publicUrl); // e.g. https://<random>.sandbox.deno.net
// Fetch from your local machine to verify
const resp = await fetch(`${publicUrl}/time`);
console.log(await resp.json());
// Keep the process alive as long as you need; when done, closing the sandbox
// will tear it down.
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
// Get SSH credentials
const { hostname, username } = await sandbox.exposeSsh();
console.log(`ssh ${username}@${hostname}`);
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
// Start a JavaScript REPL
const repl = await sandbox.repl();
// Execute code interactively, maintaining state
await repl.eval("const x = 42;");
await repl.eval("const y = 8;");
const result = await repl.eval("x + y");
console.log("result:", result); // 50
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
// Start a VSCode instance
const vscode = await sandbox.vscode();
console.log(vscode.url); // print the url of the running instance
await vscode.status; // wait until it exits
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
// Variables are automatically escaped
const filename = "file with spaces.txt";
const content = "Hello, world!";
await sandbox.sh`echo ${content} > ${filename}`;
// Arrays are expanded to multiple arguments
const files = ["file1.txt", "file2.txt", "file3.txt"];
await sandbox.sh`rm ${files}`;
// Get JSON output
const data = await sandbox.sh`echo '{"count": 42}'`.json<{ count: number }>();
console.log(data.count); // → 42
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
// Commands throw by default on non-zero exit
try {
await sandbox.sh`exit 1`;
} catch (error) {
console.log("Command failed:", error);
}
// Use noThrow() to handle errors manually
const result = await sandbox.sh`exit 1`.noThrow();
console.log("Exit code:", result.status.code); // → 1
console.log("Success:", result.status.success); // → false
import { KillController, Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
// Start a long-running command
const controller = new KillController();
const cmd = sandbox.sh`sleep 30`.signal(controller.signal);
const promise = cmd.text();
// Cancel after 2 seconds
setTimeout(() => {
controller.kill(); // Kill the process
}, 2000);
try {
await promise;
} catch (error) {
console.log("Command was cancelled:", error);
}
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
// Get both string and binary data
const result = await sandbox.sh`cat binary-file.png`
.stdout("piped");
console.log("Binary length:", result.stdout!.length);
console.log("Text length:", result.stdoutText!.length);
// Use the binary data
import fs from "node:fs";
fs.writeFileSync("output.png", result.stdout!);
import { Sandbox, SandboxCommandError } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
try {
await sandbox.sh`exit 42`;
} catch (error) {
if (error instanceof SandboxCommandError) {
console.log("Exit code:", error.code); // → 42
console.log("Error message:", error.message);
}
}
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
// Set environment variables
await sandbox.env.set("API_KEY", "secret-key-123");
await sandbox.env.set("NODE_ENV", "production");
// Use them in a script
const apiKey = await sandbox.sh`echo $API_KEY`.text();
console.log("API_KEY:", apiKey.trim());
child.stdout is a Web ReadableStream. In Node, convert a Node fs.WriteStream to a Web
WritableStream to pipe efficiently.
import { Sandbox } from "@deno/sandbox";
import fs from "node:fs";
import { Writable } from "node:stream";
await using sandbox = await Sandbox.create();
// Create a large file in the sandbox
await sandbox.writeTextFile("big.txt", "#".repeat(5_000_000));
// Stream it out to a local file
const child = await sandbox.spawn("cat", {
args: ["big.txt"],
stdout: "piped",
});
const file = fs.createWriteStream("./big-local-copy.txt");
await child.stdout.pipeTo(Writable.toWeb(file));
const status = await child.status;
console.log("done:", status);
Copy files from your machine into the sandbox using sandbox.upload(localPath, sandboxPath).
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create();
// Upload a single file to a specific path in the sandbox
await sandbox.upload("./README.md", "./readme-copy.md");
// Upload a local directory tree into the sandbox current directory
await sandbox.upload("./my-project", ".");
You can control how long your sandbox stays alive using the lifetime option:
import { Sandbox } from "@deno/sandbox";
// Default: "session" - sandbox shuts down when you close/dispose the client
await using sandbox = await Sandbox.create({ lifetime: "session" });
import { Sandbox } from "@deno/sandbox";
// Duration-based: keep sandbox alive for a specific time period
// Useful when you want the sandbox to persist after the script exits
const sandbox = await Sandbox.create({ lifetime: "5m" }); // 5 minutes
const id = sandbox.id;
// Close the *connection* to the sandbox; the sandbox keeps running
await sandbox.close();
// Later, reconnect to the same sandbox using its ID
const reconnected = await Sandbox.connect({ id });
await reconnected.sh`echo 'Still alive!'`;
// You can still forcibly terminate it before its lifetime expires
await reconnected.kill();
// At this point, the sandbox is no longer reconnectable
Supported duration suffixes: s (seconds), m (minutes). Examples: "30s", "5m", "90s".
Need other lifetime modes? Contact deploy@deno.com.
You can customize the amount of memory allocated to your sandbox using the memoryMb option. This
allows you to allocate more resources for memory-intensive workloads or reduce memory for lighter
tasks.
import { Sandbox } from "@deno/sandbox";
// Create a sandbox with 1GB of memory
await using sandbox = await Sandbox.create({ memoryMb: 1024 });
import { Sandbox } from "@deno/sandbox";
// Create a sandbox with 4GB of memory for memory-intensive workloads
await using sandbox = await Sandbox.create({ memoryMb: 4096 });
// Check available memory
const memInfo = await sandbox.eval<{ total: number }>("Deno.systemMemoryInfo()");
console.log("Total memory:", memInfo.total);
Memory limits (may change in the future):
The actual available memory inside the sandbox may be slightly less than the configured value due to system overhead.
Want to allocate more memory? Contact deploy@deno.com.
await usingThe examples use Explicit Resource Management (await using), added in Node.js 24.
For Node.js 22/23 or earlier, use try/finally:
import { Sandbox } from "@deno/sandbox";
const sandbox = await Sandbox.create();
try {
// ... use sandbox ...
} finally {
await sandbox.close();
}
Go to the console at https://app.deno.com and navigate to the Settings page where you can find
Organization Tokens section. Create a new token by clicking the Create a new token button.
At the moment you will only be able to see this if you are invited to the private alpha - email deploy@deno.com to get access.
When creating a new sandbox, the SDK communicates with the Deno Deploy API to provision a secure, isolated Linux microVM. The SDK then establishes a secure connection to the sandbox, allowing you to interact with it programmatically.
When you're done with the sandbox, you can simply destroy the Sandbox object. Doing this will
automatically shut down the sandbox and free up any resources it was using.
You can specify the region where the sandbox will be created when creating a new sandbox:
import { Sandbox } from "@deno/sandbox";
await using sandbox = await Sandbox.create({ region: "ams" });
If not specified, the sandbox will be created in the default region.
Sandboxes have the following limits:
Exceeding these limits may result in throttling or termination of your sandbox.
FAQs
> ⚠️ Deno Deploy Sandbox API is currently in private alpha. Interested in trying it out? Email > [deploy@deno.com](mailto:deploy@deno.com).
The npm package @deno/sandbox receives a total of 88 weekly downloads. As such, @deno/sandbox popularity was classified as not popular.
We found that @deno/sandbox demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 5 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Socket is heading to London! Stop by our booth or schedule a meeting to see what we've been working on.

Security News
OWASP’s 2025 Top 10 introduces Software Supply Chain Failures as a new category, reflecting rising concern over dependency and build system risks.

Research
/Security News
Socket researchers discovered nine malicious NuGet packages that use time-delayed payloads to crash applications and corrupt industrial control systems.