### Install and Run SecureExec Benchmarks Source: https://secureexec.dev/docs/benchmarks Clone the repository, install dependencies, and run the benchmarks. This command installs all necessary packages and then executes the main benchmark script. ```bash # Clone and install git clone https://github.com/rivet-dev/secure-exec cd secure-exec && pnpm install # Run both benchmarks (saves timestamped results to benchmarks/results/) cd packages/secure-exec ./benchmarks/run-benchmarks.sh ``` -------------------------------- ### Custom Network Adapter Setup Source: https://secureexec.dev/docs/features/networking This example demonstrates how to configure Secure Exec with a custom network adapter in a Node.js environment. It uses `createDefaultNetworkAdapter` but allows for more granular control by providing it explicitly. ```typescript import { createNodeDriver, createDefaultNetworkAdapter, allowAllNetwork } from "secure-exec"; const driver = createNodeDriver({ networkAdapter: createDefaultNetworkAdapter(), permissions: { ...allowAllNetwork }, }); ``` -------------------------------- ### Configure Filesystem Access with Permissions Source: https://secureexec.dev/docs/features/permissions This example demonstrates how to configure filesystem permissions, allowing access only to paths starting with '/workspace' while denying access to '/secret.txt'. It verifies that the sandbox can write to an allowed path and attempts to read from a denied path, confirming the access control. ```typescript import { NodeRuntime, createInMemoryFileSystem, createNodeDriver, createNodeRuntimeDriverFactory, } from "../../../packages/secure-exec/src/index.ts"; const filesystem = createInMemoryFileSystem(); await filesystem.writeFile("/secret.txt", "top secret"); const runtime = new NodeRuntime({ systemDriver: createNodeDriver({ filesystem, permissions: { fs: (request) => ({ allow: request.path.startsWith("/workspace") }), }, }), runtimeDriverFactory: createNodeRuntimeDriverFactory(), }); const result = await runtime.run<{ message: string; blocked: boolean; }>( ` import fs from "node:fs"; fs.mkdirSync("/workspace", { recursive: true }); fs.writeFileSync("/workspace/message.txt", "hello from permissions"); let blocked = false; try { fs.readFileSync("/secret.txt", "utf8"); } catch (error) { blocked = error && error.code === "EACCES"; } export const message = fs.readFileSync("/workspace/message.txt", "utf8"); export { blocked }; `, "/entry.mjs", ); console.log( JSON.stringify({ ok: result.code === 0 && result.exports?.message === "hello from permissions" && result.exports?.blocked === true, message: result.exports?.message, blocked: result.exports?.blocked, summary: "filesystem access was allowed for /workspace and denied for /secret.txt", }), ); ``` -------------------------------- ### Install secure-exec with bun Source: https://secureexec.dev/docs/sdk-overview Install the secure-exec package using bun. ```bash bun add secure-exec ``` -------------------------------- ### Runnable Example: In-Memory Filesystem Source: https://secureexec.dev/docs/features/filesystem Demonstrates writing to and reading from an in-memory filesystem within a sandboxed environment. This example requires importing necessary components from 'secure-exec'. ```typescript import { NodeRuntime, allowAllFs, createInMemoryFileSystem, createNodeDriver, createNodeRuntimeDriverFactory, } from "../../../packages/secure-exec/src/index.ts"; const filesystem = createInMemoryFileSystem(); const runtime = new NodeRuntime({ systemDriver: createNodeDriver({ filesystem, permissions: { ...allowAllFs }, }), runtimeDriverFactory: createNodeRuntimeDriverFactory(), }); try { const result = await runtime.exec( ` import fs from "node:fs"; fs.mkdirSync("/workspace", { recursive: true }); fs.writeFileSync("/workspace/hello.txt", "hello from the sandbox"); `, { filePath: "/entry.mjs" }, ); if (result.code !== 0) { throw new Error(`Unexpected execution result: ${JSON.stringify(result)}`); } const message = await filesystem.readTextFile("/workspace/hello.txt"); console.log( JSON.stringify({ ok: message === "hello from the sandbox", message, summary: "sandbox wrote to the in-memory filesystem", }), ); } finally { runtime.dispose(); } ``` -------------------------------- ### Install SecureExec Source: https://secureexec.dev/docs Install the SecureExec package using npm. ```bash npm install secure-exec ``` -------------------------------- ### Quick Setup for Network Access Source: https://secureexec.dev/docs/features/networking This snippet shows the basic setup for enabling network access in a Node.js environment using Secure Exec. It configures the driver to allow all network traffic and uses the default network adapter. ```typescript import { createNodeDriver, allowAllNetwork } from "secure-exec"; const driver = createNodeDriver({ useDefaultNetwork: true, permissions: { ...allowAllNetwork }, }); ``` -------------------------------- ### Shared Setup for TypeScript Tools Source: https://secureexec.dev/docs/runtimes/node This code demonstrates the shared setup required for using the `@secure-exec/typescript` package, including creating file system and driver instances. ```typescript import { createInMemoryFileSystem } from "@secure-exec/core"; import { createNodeDriver, createNodeRuntimeDriverFactory, } from "@secure-exec/nodejs"; import { createTypeScriptTools } from "@secure-exec/typescript"; const filesystem = createInMemoryFileSystem(); const systemDriver = createNodeDriver({ filesystem }); const runtimeDriverFactory = createNodeRuntimeDriverFactory(); const ts = createTypeScriptTools({ systemDriver, runtimeDriverFactory, }); ``` -------------------------------- ### Install secure-exec with yarn Source: https://secureexec.dev/docs/sdk-overview Install the secure-exec package using yarn. ```bash yarn add secure-exec ``` -------------------------------- ### Install secure-exec with npm Source: https://secureexec.dev/docs/sdk-overview Install the secure-exec package using npm. ```bash npm install secure-exec ``` -------------------------------- ### Install secure-exec with pnpm Source: https://secureexec.dev/docs/sdk-overview Install the secure-exec package using pnpm. ```bash pnpm add secure-exec ``` -------------------------------- ### Runnable Network Access Example Source: https://secureexec.dev/docs/features/networking This example demonstrates enabling network access for a sandboxed Node.js environment to fetch data from a host-managed HTTP server. It requires setting up a loopback server, configuring the Secure Exec runtime with network permissions, and executing a fetch request within the sandbox. ```typescript import * as http from "node:http"; import { NodeRuntime, allowAllNetwork, createDefaultNetworkAdapter, createNodeDriver, createNodeRuntimeDriverFactory, } from "../../../packages/secure-exec/src/index.ts"; const logs: string[] = []; const server = http.createServer((_req, res) => { res.writeHead(200, { "content-type": "text/plain" }); res.end("network-ok"); }); await new Promise((resolve, reject) => { server.once("error", reject); server.listen(0, "127.0.0.1", () => resolve()); }); const address = server.address(); if (!address || typeof address === "string") { throw new Error("missing loopback address"); } const runtime = new NodeRuntime({ systemDriver: createNodeDriver({ networkAdapter: createDefaultNetworkAdapter({ initialExemptPorts: [address.port], }), permissions: { ...allowAllNetwork }, }), runtimeDriverFactory: createNodeRuntimeDriverFactory(), }); try { const result = await runtime.exec( ` (async () => { const response = await fetch("http://127.0.0.1:${address.port}/"); const body = await response.text(); if (!response.ok || response.status !== 200 || body !== "network-ok") { throw new Error( "unexpected response: " + response.status + " " + body, ); } console.log(JSON.stringify({ status: response.status, body })); })().catch((error) => { console.error(error instanceof Error ? error.message : String(error)); process.exitCode = 1; }); `, { onStdio: (event) => { logs.push(`[${event.channel}] ${event.message}`); }, }, ); if (result.code !== 0) { throw new Error(`Unexpected execution result: ${JSON.stringify(result)}`); } const payload = logs .filter((line) => line.startsWith("[stdout] ")) .map((line) => line.slice("[stdout] ".length)) .map((line) => JSON.parse(line)) .at(-1); if (payload?.status !== 200 || payload?.body !== "network-ok") { throw new Error(`Unexpected captured output: ${JSON.stringify(logs)}`); } console.log( JSON.stringify({ ok: true, status: payload.status, body: payload.body, summary: "sandbox fetched a host-managed loopback HTTP server", }), ); } finally { runtime.dispose(); await new Promise((resolve, reject) => { server.close((error) => { if (error) reject(error); else resolve(); }); }); } ``` -------------------------------- ### Install TypeScript tools Source: https://secureexec.dev/docs/sdk-overview Install the optional companion package for sandboxed type checking and compilation. ```bash pnpm add @secure-exec/typescript ``` -------------------------------- ### Run TypeScript Example with Module Resolution Source: https://secureexec.dev/docs/features/module-loading This example demonstrates running a TypeScript script within a sandbox, importing and accessing the 'typescript' package from the host's node_modules. ```typescript import path from "node:path"; import { fileURLToPath } from "node:url"; import { NodeRuntime, allowAllFs, createNodeDriver, createNodeRuntimeDriverFactory, } from "../../../packages/secure-exec/src/index.ts"; const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../.."); const runtime = new NodeRuntime({ systemDriver: createNodeDriver({ moduleAccess: { cwd: repoRoot }, permissions: { ...allowAllFs }, }), runtimeDriverFactory: createNodeRuntimeDriverFactory(), }); try { const result = await runtime.run<{ version: string }>( ` import typescript from "/root/node_modules/typescript/lib/typescript.js"; export const version = typescript.version; `, "/app/example.mjs", ); if (result.code !== 0 || typeof result.exports?.version !== "string") { throw new Error(`Unexpected runtime result: ${JSON.stringify(result)}`); } console.log( JSON.stringify({ ok: true, version: result.exports.version, summary: "sandbox resolved the host typescript package from the overlay", }), ); } finally { runtime.dispose(); } ``` -------------------------------- ### Runnable Example: Spawn Node Version Source: https://secureexec.dev/docs/features/child-processes This example demonstrates spawning a child process ('node --version') from within a sandboxed Node.js runtime. It utilizes a custom `CommandExecutor` and verifies the output. ```typescript import { NodeRuntime, allowAllChildProcess, createNodeDriver, createNodeRuntimeDriverFactory, } from "../../../packages/secure-exec/src/index.ts"; import type { CommandExecutor } from "../../../packages/secure-exec/src/types.ts"; import { spawn } from "node:child_process"; const commandExecutor: CommandExecutor = { spawn(command, args, options) { const resolvedCommand = command === "node" ? process.execPath : command; const resolvedCwd = options.cwd === "/root" ? process.cwd() : options.cwd; const child = spawn(resolvedCommand, args, { cwd: resolvedCwd, env: options.env, stdio: ["pipe", "pipe", "pipe"], }); child.stdout.on("data", (chunk) => { options.onStdout?.(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)); }); child.stderr.on("data", (chunk) => { options.onStderr?.(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)); }); return { writeStdin(data) { child.stdin.write(data); }, closeStdin() { child.stdin.end(); }, kill(signal) { child.kill(signal); }, wait() { return new Promise((resolve) => { child.once("close", (code) => resolve(code ?? 1)); }); }, }; }, }; const runtime = new NodeRuntime({ systemDriver: createNodeDriver({ commandExecutor, permissions: { ...allowAllChildProcess }, }), runtimeDriverFactory: createNodeRuntimeDriverFactory(), }); try { const result = await runtime.exec( ` import { spawnSync } from "node:child_process"; const child = spawnSync("node", ["--version"], { encoding: "utf8", }); const output = typeof child.stdout === "string" ? child.stdout : Buffer.from(child.stdout || []).toString("utf8"); if (child.status !== 0 || !output.startsWith("v")) { throw new Error("Unexpected child process exit code: " + child.status); } `, { filePath: "/entry.mjs" } ); if (result.code !== 0) { throw new Error(`Unexpected execution result: ${JSON.stringify(result)}`); } console.log( JSON.stringify({ ok: true, summary: "sandbox spawned node --version successfully", }) ); } finally { runtime.dispose(); } ``` -------------------------------- ### Install Secure Exec Source: https://secureexec.dev/docs/quickstart Install the secure-exec package using your preferred package manager (npm, pnpm, bun, or yarn). ```bash npm install secure-exec ``` ```bash pnpm add secure-exec ``` ```bash bun add secure-exec ``` ```bash yarn add secure-exec ``` -------------------------------- ### Interact with Virtual Filesystem Source: https://secureexec.dev/docs/quickstart Configure the runtime with a virtual filesystem (e.g., `createInMemoryFileSystem`) and permissions to allow file operations within the sandbox. This example creates a directory and writes a file. ```typescript import { NodeRuntime, createNodeDriver, createNodeRuntimeDriverFactory, createInMemoryFileSystem, allowAllFs, } from "secure-exec"; const filesystem = createInMemoryFileSystem(); const runtime = new NodeRuntime({ systemDriver: createNodeDriver({ filesystem, permissions: { ...allowAllFs }, }), runtimeDriverFactory: createNodeRuntimeDriverFactory(), }); await runtime.exec(` import fs from "node:fs"; fs.mkdirSync("/workspace", { recursive: true }); fs.writeFileSync("/workspace/hello.txt", "hello from the sandbox"); `, { filePath: "/entry.mjs" }); const bytes = await filesystem.readFile("/workspace/hello.txt"); console.log(new TextDecoder().decode(bytes)); // "hello from the sandbox" runtime.dispose(); ``` -------------------------------- ### Runnable Example: CPU and Memory Limits Source: https://secureexec.dev/docs/features/resource-limits Demonstrates setting both CPU time and memory limits for a runtime. It executes normal code and an infinite loop to verify that the CPU limit is enforced. ```typescript import { NodeRuntime, createNodeDriver, createNodeRuntimeDriverFactory, } from "../../../packages/secure-exec/src/index.ts"; const runtime = new NodeRuntime({ systemDriver: createNodeDriver(), runtimeDriverFactory: createNodeRuntimeDriverFactory(), memoryLimit: 64, cpuTimeLimitMs: 100, }); try { const safeRun = await runtime.exec(` console.log("resource-limits-ok"); `); const timedOut = await runtime.exec("while (true) {}"); const success = safeRun.code === 0 && timedOut.code === 124 && (timedOut.errorMessage?.includes("CPU time limit exceeded") ?? false); console.log( JSON.stringify({ ok: success, safeCode: safeRun.code, timeoutCode: timedOut.code, errorMessage: timedOut.errorMessage, summary: "normal code completed and an infinite loop hit the CPU limit", }), ); } finally { runtime.dispose(); } ``` -------------------------------- ### Execute Code with SecureExec Source: https://secureexec.dev/docs/quickstart This snippet shows how to initialize SecureExec, execute a JavaScript module, and access its exports. Ensure you have the 'secure-exec' package installed. ```javascript import { SecureExec } from "secure-exec"; const runtime = new SecureExec(); const result = await runtime.execute( ` export const sum = 1 + 2; export const greeting = greet("secure-exec"); `, "/app/entry.mjs" ); console.log(result.exports?.sum); // 3 console.log(result.exports?.greeting); // "hello, secure-exec" runtime.dispose(); ``` -------------------------------- ### Run Cold and Warm Start Benchmark Source: https://secureexec.dev/docs/benchmarks Execute the cold and warm start benchmark script using tsx. This measures the performance difference between an initialized and a newly created runtime. ```bash npx tsx benchmarks/coldstart.bench.ts ``` -------------------------------- ### Enable Network Access for Fetch Source: https://secureexec.dev/docs/quickstart Configure the runtime to allow network requests using `useDefaultNetwork: true` and `allowAllNetwork` permissions. This example demonstrates fetching data from an external URL. ```typescript import { NodeRuntime, createNodeDriver, createNodeRuntimeDriverFactory, allowAllNetwork, } from "secure-exec"; const runtime = new NodeRuntime({ systemDriver: createNodeDriver({ useDefaultNetwork: true, permissions: { ...allowAllNetwork }, }), runtimeDriverFactory: createNodeRuntimeDriverFactory(), onStdio: (event) => { process.stdout.write(event.message); }, }); await runtime.exec(` const response = await fetch("https://example.com"); console.log(response.status); // 200 `, { filePath: "/entry.mjs" }); runtime.dispose(); ``` -------------------------------- ### Preset Permission Configurations Source: https://secureexec.dev/docs/features/permissions Provides quick presets for common permission configurations, such as allowing all operations or selectively allowing filesystem and network access. These presets simplify the setup for typical use cases. ```typescript import { createNodeDriver, allowAll, allowAllFs, allowAllNetwork, } from "secure-exec"; // Allow everything const driver = createNodeDriver({ permissions: allowAll }); // Allow only filesystem and network const selective = createNodeDriver({ permissions: { ...allowAllFs, ...allowAllNetwork, }, }); ``` -------------------------------- ### Implement Function-Based Permissions for Node Driver Source: https://secureexec.dev/docs/system-drivers/node Defines granular permissions for filesystem, network, child process, and environment variable access using callback functions. This example allows writing to /tmp, network access to api.example.com, execution of 'ls' commands, and access to NODE_ENV and PATH environment variables. ```typescript import type { FsAccessRequest, NetworkAccessRequest, ChildProcessAccessRequest, EnvAccessRequest, PermissionDecision, } from "secure-exec"; const driver = createNodeDriver({ permissions: { fs: (request: FsAccessRequest): PermissionDecision => { if (request.path.startsWith("/tmp")) return { allow: true }; return { allow: false, reason: "Only /tmp is writable" }; }, network: (request: NetworkAccessRequest): PermissionDecision => { if (request.hostname === "api.example.com") return { allow: true }; return { allow: false }; }, childProcess: (request: ChildProcessAccessRequest): PermissionDecision => { if (request.command === "ls") return { allow: true }; return { allow: false, reason: `Blocked command: ${request.command}` }; }, env: (request: EnvAccessRequest): PermissionDecision => { if (["NODE_ENV", "PATH"].includes(request.key)) return { allow: true }; return { allow: false }; }, }, }); ``` -------------------------------- ### Run a Sandboxed Hono Dev Server Source: https://secureexec.dev/docs/use-cases/dev-servers Starts a user-provided Hono server inside an isolate, waits for its health endpoint, fetches a response, and then terminates the isolate. This is useful for previewing user-written server-side code in a secure environment. ```typescript import { createServer } from "node:net"; import { NodeRuntime, allowAllNetwork, createNodeDriver, createNodeRuntimeDriverFactory, } from "secure-exec"; const host = "127.0.0.1"; const port = await findOpenPort(); const logs: string[] = []; const runtime = new NodeRuntime({ systemDriver: createNodeDriver({ useDefaultNetwork: true, permissions: { ...allowAllNetwork }, }), runtimeDriverFactory: createNodeRuntimeDriverFactory(), memoryLimit: 128, cpuTimeLimitMs: 60_000, }); const execPromise = runtime.exec (` import { Hono } from "hono"; import { serve } from "@hono/node-server"; const app = new Hono(); app.get("/", (c) => c.text("hello from sandboxed hono")); app.get("/health", (c) => c.json({ ok: true })); serve({ fetch: app.fetch, port: ${port}, hostname: "${host}", }); console.log("server:listening:${port}"); await new Promise(() => {}); `, { filePath: "/app/server.mjs", onStdio: (event) => logs.push(`[${event.channel}] ${event.message}`), }); try { await waitForServer(runtime, `http://${host}:${port}/health`); const response = await runtime.network.fetch(`http://${host}:${port}/`, { method: "GET", }); console.log(response.status); // 200 console.log(response.body); // "hello from sandboxed hono" } finally { await runtime.terminate(); await execPromise.catch(() => undefined); } async function findOpenPort(): Promise { return new Promise((resolve, reject) => { const server = createServer(); server.once("error", reject); server.listen(0, host, () => { const address = server.address(); if (!address || typeof address !== "object") { reject(new Error("Failed to allocate a port")); server.close(); return; } const allocatedPort = address.port; server.close((error) => { if (error) { reject(error); return; } resolve(allocatedPort); }); }); }); } async function waitForServer(runtime: NodeRuntime, url: string): Promise { for (let attempt = 0; attempt < 50; attempt += 1) { try { const response = await runtime.network.fetch(url, { method: "GET" }); if (response.status === 200) { return; } } catch { // Retry until the server is ready. } await new Promise((resolve) => setTimeout(resolve, 100)); } throw new Error(`Timed out waiting for ${url}`); } ``` -------------------------------- ### Create and Mount Node Runtime with Kernel Source: https://secureexec.dev/docs/runtimes/node This snippet demonstrates the kernel-first approach to setting up the Node runtime. It creates a kernel with an in-memory file system, mounts the Node runtime driver, executes a simple JavaScript command, and then disposes of the kernel. ```typescript import { createKernel, createInMemoryFileSystem, createNodeRuntime, } from "secure-exec"; const kernel = createKernel({ filesystem: createInMemoryFileSystem(), }); await kernel.mount(createNodeRuntime()); const result = await kernel.exec("node -e \"console.log('hello')\""); console.log(result.stdout); // "hello\n" await kernel.dispose(); ``` -------------------------------- ### Run a Plugin from an In-Memory Filesystem Source: https://secureexec.dev/docs/use-cases/plugin-systems This snippet demonstrates how to load and run a plugin from an in-memory virtual filesystem. It sets up the filesystem, writes the plugin code, and configures a NodeRuntime with specific resource limits and filesystem permissions. The plugin is then executed, and its output is logged. ```ts import { NodeRuntime, allowAllFs, createInMemoryFileSystem, createNodeDriver, createNodeRuntimeDriverFactory, } from "secure-exec"; const filesystem = createInMemoryFileSystem(); await filesystem.mkdir("/plugins"); await filesystem.writeFile( "/plugins/title-case.mjs", ` export const manifest = { name: "title-case", version: "1.0.0", }; export function transform(input, options = {}) { const words = String(input) .split(/\s+/) // Split by whitespace .filter(Boolean) // Remove empty strings .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()); // Capitalize first letter of each word return (options.prefix ?? "") + words.join(" "); // Join words with a space and add optional prefix } ` ); const runtime = new NodeRuntime({ systemDriver: createNodeDriver({ filesystem, permissions: { ...allowAllFs }, // Grant all filesystem permissions }), runtimeDriverFactory: createNodeRuntimeDriverFactory(), memoryLimit: 64, // 64MB memory limit cpuTimeLimitMs: 1000, // 1 second CPU time limit }); const input = "hello from plugin land"; const options = { prefix: "Plugin says: " }; const result = await runtime.run({ // The code to be executed within the plugin runtime code: ` import { manifest, transform } from "/plugins/title-case.mjs"; export { manifest }; export const output = transform( ${JSON.stringify(input)}, ${JSON.stringify(options)} ); `, // The entrypoint for the plugin code entrypoint: "/root/run-plugin.mjs", }); console.log(result.exports?.manifest.name); // Expected output: "title-case" console.log(result.exports?.output); // Expected output: "Plugin says: Hello From Plugin Land" ``` -------------------------------- ### Create a system driver with all permissions allowed Source: https://secureexec.dev/docs/sdk-overview Initializes a Node.js system driver that grants all possible host capabilities to the sandboxed code. ```typescript import { createNodeDriver, allowAll, allowAllFs } from "secure-exec"; // Allow everything const driver = createNodeDriver({ permissions: allowAll }); ``` -------------------------------- ### Custom Command Executor Example Source: https://secureexec.dev/docs/system-drivers/node Implement a custom `CommandExecutor` using Node.js's built-in `child_process.spawn`. This example restricts execution to only the `node` command. ```typescript import { spawn } from "node:child_process"; import type { CommandExecutor } from "secure-exec"; const commandExecutor: CommandExecutor = { spawn(command, args, options) { const proc = spawn(command, args, { cwd: options.cwd, env: options.env, }); proc.stdout?.on("data", (chunk) => options.onStdout?.(chunk)); proc.stderr?.on("data", (chunk) => options.onStderr?.(chunk)); return { writeStdin: (data) => proc.stdin?.write(data), closeStdin: () => proc.stdin?.end(), kill: (signal) => proc.kill(signal), wait: () => new Promise((resolve) => proc.on("close", (code) => resolve(code ?? 1)), ), }; }, }; const driver = createNodeDriver({ commandExecutor, permissions: { childProcess: (req) => { if (req.command === "node") return { allow: true }; return { allow: false }; }, }, }); ``` -------------------------------- ### Create and Use Kernel API Source: https://secureexec.dev/docs/quickstart This snippet shows how to initialize the SecureExec kernel, mount a Node.js runtime, and spawn a child process. Use this for managing shell commands and inter-process communication. ```typescript import { createKernel, createInMemoryFileSystem, createNodeRuntime, } from "secure-exec"; const kernel = createKernel({ filesystem: createInMemoryFileSystem(), }); await kernel.mount(createNodeRuntime()); // spawn() runs a command directly (no shell needed) const proc = kernel.spawn("node", ["-e", "console.log('hello')"], { onStdout: (data) => process.stdout.write(data), }); await proc.wait(); await kernel.dispose(); ``` -------------------------------- ### Node.js Runtime Initialization and Execution Source: https://secureexec.dev/docs/architecture Initializes the NodeRuntime with a system driver and demonstrates executing a string and running a module. ```typescript import { NodeRuntime, createNodeDriver } from "secure-exec"; const runtime = new NodeRuntime({ systemDriver: createNodeDriver(), }); await runtime.exec("console.log('hello')"); await runtime.run("export default 42"); runtime.dispose(); ``` -------------------------------- ### Run JavaScript Code with Exports Source: https://secureexec.dev/docs Execute JavaScript code using `runtime.run()` and retrieve exported values. The example demonstrates exporting a message and logging it. ```typescript import { NodeRuntime, createNodeDriver, createNodeRuntimeDriverFactory, } from "secure-exec"; const runtime = new NodeRuntime({ systemDriver: createNodeDriver(), runtimeDriverFactory: createNodeRuntimeRuntimeDriverFactory(), }); const result = await runtime.run<{ message: string }>( `export const message = "hello from secure-exec";` ); console.log(result.exports?.message); // "hello from secure-exec" runtime.dispose(); ``` -------------------------------- ### Permission Gating for Child Processes Source: https://secureexec.dev/docs/features/child-processes Restrict which commands sandboxed code can spawn by defining a `childProcess` permission function. This example allows only 'node', 'python3', and 'echo'. ```typescript const driver = createNodeDriver({ permissions: { childProcess: (req) => { const allowed = ["node", "python3", "echo"]; return { allow: allowed.includes(req.command) }; }, }, }); ``` -------------------------------- ### Configure Node Driver with Capabilities Source: https://secureexec.dev/docs/system-drivers/node Sets up the Node driver with enabled network access, all filesystem permissions, and a specified working directory and environment variables for child processes. ```typescript import { createNodeDriver, createDefaultNetworkAdapter, allowAllFs, allowAllNetwork, } from "secure-exec"; const driver = createNodeDriver({ useDefaultNetwork: true, permissions: { fs: allowAllFs, network: allowAllNetwork, }, processConfig: { cwd: "/app", env: { NODE_ENV: "production" }, }, }); ``` -------------------------------- ### Kernel API for Multi-Process Workloads Source: https://secureexec.dev/docs Utilize the kernel API for shell commands, child processes, and inter-process communication. This example mounts a Node.js runtime and spawns a Node.js process. ```typescript import { createKernel, createInMemoryFileSystem, createNodeRuntime, } from "secure-exec"; const kernel = createKernel({ filesystem: createInMemoryFileSystem(), }); await kernel.mount(createNodeRuntime()); // spawn() runs a command directly (no shell needed) const proc = kernel.spawn("node", ["-e", "console.log('hello')"], { onStdout: (data) => process.stdout.write(data), }); await proc.wait(); await kernel.dispose(); ``` -------------------------------- ### Initialize Node.js File System Source: https://secureexec.dev/docs/api-reference Create a filesystem wrapper that directly interfaces with Node.js's built-in `fs/promises` module. This provides a thin layer over native filesystem operations. ```typescript new NodeFileSystem() ``` -------------------------------- ### Permission Gating Network Requests Source: https://secureexec.dev/docs/features/networking Implement a function for `permissions.network` to filter incoming network requests based on hostname. This example blocks requests to `.internal` domains and the metadata service IP. ```typescript const driver = createNodeDriver({ useDefaultNetwork: true, permissions: { network: (req) => { if (req.hostname?.endsWith(".internal")) { return { allow: false }; } if (req.hostname === "169.254.169.254") { return { allow: false }; } return { allow: true }; }, }, }); ``` -------------------------------- ### Node.js Filesystem Wrapper Source: https://secureexec.dev/docs/features/filesystem Initializes a NodeFileSystem instance, which acts as a thin wrapper around Node.js's 'fs/promises' module. This provides real host filesystem access, subject to configured permissions. ```typescript import { NodeFileSystem } from "secure-exec"; const fs = new NodeFileSystem(); ``` -------------------------------- ### Using Read-Only Map Filesystem with NodeRuntime Source: https://secureexec.dev/docs/features/virtual-filesystem Demonstrates initializing a NodeRuntime with a custom read-only Map filesystem and executing code within it. ```typescript const fs = new ReadOnlyMapFS({ "/config.json": JSON.stringify({ greeting: "hello" }), "/src/index.mjs": " import { readFileSync } from \"node:fs\"; const config = JSON.parse(readFileSync(\"/config.json\", \"utf8\")); console.log(config.greeting); ", }); const runtime = new NodeRuntime({ systemDriver: createNodeDriver({ filesystem: fs, permissions: { ...allowAllFs }, }), runtimeDriverFactory: createNodeRuntimeDriverFactory(), }); const result = await runtime.exec( ` import { readFileSync } from \"node:fs\"; const config = JSON.parse(readFileSync(\"/config.json\", \"utf8\")); console.log(config.greeting); `, { filePath: "/entry.mjs" } ); // Output captured via onStdio callback — see Output Capture docs runtime.dispose(); ``` -------------------------------- ### Capture stdout and stderr with onStdio hook Source: https://secureexec.dev/docs/features/output-capture This example demonstrates capturing both standard output and standard error from a sandboxed execution using the `onStdio` hook. It verifies that the captured messages match the expected output. ```typescript import { NodeRuntime, createNodeDriver, createNodeRuntimeDriverFactory, } from "../../../packages/secure-exec/src/index.ts"; const events: string[] = []; const runtime = new NodeRuntime({ systemDriver: createNodeDriver(), runtimeDriverFactory: createNodeRuntimeDriverFactory(), }); try { const result = await runtime.exec( ` console.log("hello from the sandbox"); console.error("oops from the sandbox"); `, { onStdio: (event) => { events.push(`[${event.channel}] ${event.message}`); }, } ); if (result.code !== 0) { throw new Error(`Unexpected execution result: ${JSON.stringify(result)}`); } const expected = [ "[stdout] hello from the sandbox", "[stderr] oops from the sandbox", ]; if (JSON.stringify(events) !== JSON.stringify(expected)) { throw new Error(`Unexpected stdio events: ${JSON.stringify(events)}`); } console.log( JSON.stringify({ ok: true, events, summary: "captured stdout and stderr with onStdio", }), ); } finally { runtime.dispose(); } ``` -------------------------------- ### Type Check a TypeScript Project from Filesystem Source: https://secureexec.dev/docs/runtimes/node Use `typecheckProject` to validate a full TypeScript project, including `tsconfig.json` and source files, from the sandbox filesystem. This example shows setting up a project structure and performing type checking. ```typescript await filesystem.mkdir("/root/src"); await filesystem.writeFile( "/root/tsconfig.json", JSON.stringify({ compilerOptions: { module: "nodenext", moduleResolution: "nodenext", target: "es2022", }, include: ["src/**/*.ts"], }), ); await filesystem.writeFile( "/root/src/index.ts", "export const value: string = 123;\n", ); const result = await ts.typecheckProject({ cwd: "/root" }); console.log(result.success); // false console.log(result.diagnostics[0]?.message); ``` -------------------------------- ### Pre-built Permissions Helpers Source: https://secureexec.dev/docs/api-reference Provides pre-built helpers for common permission configurations. ```APIDOC ## Permissions Helpers - **allowAll**: Allows all operations. - **allowAllFs**: Allows all filesystem operations. - **allowAllNetwork**: Allows all network operations. - **allowAllChildProcess**: Allows all child process spawning. - **allowAllEnv**: Allows all environment variable access. ``` -------------------------------- ### Create TypeScript Tools Source: https://secureexec.dev/docs/api-reference Instantiate TypeScript project helpers with custom options for sandboxed compilation and type-checking. Configure memory, CPU limits, and compiler loading. ```typescript createTypeScriptTools(options: TypeScriptToolsOptions) ``` -------------------------------- ### Process and OS Configuration Source: https://secureexec.dev/docs/system-drivers/node Configure sandbox environment variables, working directory, and OS platform/architecture. This controls what the sandboxed code sees for `process` and `os` APIs. ```typescript const driver = createNodeDriver({ processConfig: { cwd: "/app", env: { NODE_ENV: "production", API_KEY: "sk-..." }, }, osConfig: { platform: "linux", arch: "x64", }, }); ``` -------------------------------- ### NodeRuntime exec() vs run() Signatures Source: https://secureexec.dev/docs/runtimes/node Illustrates the different signatures and intended use cases for the exec() and run() methods of the NodeRuntime class. exec() is for observing output and environment control, while run() is for getting computed values. ```typescript // Process-style execution — observe stdout/stderr, set env/cwd/stdin exec(code: string, options?: ExecOptions): Promise // Export-based evaluation — get computed values back run(code: string, filePath?: string): Promise> ``` -------------------------------- ### createNodeRuntime Source: https://secureexec.dev/docs/api-reference Creates a Node.js runtime driver that can be mounted into a kernel via kernel.mount(). ```APIDOC ## createNodeRuntime(options?) ### Description Creates a Node.js runtime driver that can be mounted into a kernel via `kernel.mount()`. ### Method Signature ```ts createNodeRuntime(options?: { memoryLimit?: number; moduleAccessPaths?: string[]; permissions?: Partial; }): RuntimeDriver ``` ### Parameters #### Options - **memoryLimit** (`number`) - Optional - Memory limit in MB for each V8 isolate. Default `128`. - **moduleAccessPaths** (`string[]`) - Optional - Host filesystem paths for module resolution. - **permissions** (`Partial`) - Optional - Bridge permissions for isolate processes. ``` -------------------------------- ### Registering Custom Bindings in NodeRuntime Source: https://secureexec.dev/docs/features/custom-bindings Register a `bindings` object when creating the `NodeRuntime`. Each leaf function becomes callable from sandbox code via `SecureExec.bindings`. This example shows how to bind database and cache operations, along with a simple greeting function. ```typescript import { NodeRuntime, createNodeDriver, createNodeRuntimeDriverFactory, } from "@anthropic-ai/secure-exec"; const runtime = new NodeRuntime({ systemDriver: createNodeDriver(), runtimeDriverFactory: createNodeRuntimeDriverFactory(), bindings: { db: { query: async (sql, params) => db.query(sql, params), insert: async (sql, values) => db.insert(sql, values), }, cache: { get: async (key) => redis.get(key), set: async (key, val) => redis.set(key, val), }, greet: (name) => `Hello, ${name}!`, }, }); ``` -------------------------------- ### createKernel Source: https://secureexec.dev/docs/api-reference Creates a kernel that manages a virtual filesystem, process table, file descriptor table, pipes, PTYs, and permissions. Mount runtime drivers to execute code. ```APIDOC ## createKernel(options) ### Description Creates a kernel that manages a virtual filesystem, process table, file descriptor table, pipes, PTYs, and permissions. Mount runtime drivers to execute code. ### Method Signature ```ts createKernel(options: KernelOptions): Kernel ``` ### Parameters #### KernelOptions - **filesystem** (`VirtualFileSystem`) - Required - Virtual filesystem for the kernel. - **permissions** (`Permissions`) - Optional - Access control rules. Deny-by-default. - **env** (`Record`) - Optional - Environment variables. - **cwd** (`string`) - Optional - Working directory. Default `"/root"`. - **maxProcesses** (`number`) - Optional - Maximum concurrent processes. ### Kernel Methods #### `mount(driver)` - **Returns**: `Promise` - **Description**: Mount a runtime driver. #### `exec(command, options?)` - **Returns**: `Promise` - **Description**: Execute a command string through the shell. #### `spawn(command, args, options?)` - **Returns**: `ManagedProcess` - **Description**: Spawn a process directly (no shell). #### `openShell(options?)` - **Returns**: `ShellHandle` - **Description**: Open an interactive shell on a PTY. #### `connectTerminal(options?)` - **Returns**: `Promise` - **Description**: Wire a shell to process.stdin/stdout. #### `readFile(path)` - **Returns**: `Promise` - **Description**: Read a file from VFS. #### `writeFile(path, content)` - **Returns**: `Promise` - **Description**: Write a file to VFS. #### `mkdir(path)` - **Returns**: `Promise` - **Description**: Create a directory. #### `readdir(path)` - **Returns**: `Promise` - **Description**: List directory entries. #### `stat(path)` - **Returns**: `Promise` - **Description**: Get file metadata. #### `exists(path)` - **Returns**: `Promise` - **Description**: Check if a path exists. #### `dispose()` - **Returns**: `Promise` - **Description**: Dispose the kernel and all mounted drivers. ### KernelExecResult ```ts { exitCode: number; stdout: string; stderr: string; } ``` ``` -------------------------------- ### AI SDK Tool Loop with exec() Source: https://secureexec.dev/docs/runtimes/node Demonstrates using the exec() method for an AI SDK tool loop, capturing stdout from each step and setting environment variables. This is suitable when the result is communicated through console.log. ```typescript // AI SDK tool loop — capture stdout from each step for (const step of toolSteps) { const result = await runtime.exec(step.code, { onStdio: (e) => appendToToolResult(e.message), env: { API_KEY: step.apiKey }, cwd: "/workspace", }); if (result.code !== 0) handleError(result); } ``` -------------------------------- ### Create Default Network Adapter Source: https://secureexec.dev/docs/api-reference Creates a network adapter with real fetch, DNS, and HTTP client support. This is only available in Node.js environments. ```typescript createDefaultNetworkAdapter(): NetworkAdapter ``` -------------------------------- ### Create a system driver with custom network permission Source: https://secureexec.dev/docs/sdk-overview Initializes a Node.js system driver with custom network permissions, allowing connections only to hosts that are not 'internal.corp'. ```typescript // Custom check const filtered = createNodeDriver({ permissions: { network: (req) => req.hostname !== "internal.corp", }, }); ``` -------------------------------- ### Run Multi-File Modules Source: https://secureexec.dev/docs/quickstart Execute code that imports modules from a virtual filesystem. Write module files to the filesystem first, then use `runtime.run()` to execute an entry point that imports them. ```typescript import { NodeRuntime, createNodeDriver, createNodeRuntimeDriverFactory, createInMemoryFileSystem, allowAllFs, } from "secure-exec"; const filesystem = createInMemoryFileSystem(); // Write module files to the virtual filesystem await filesystem.writeFile( "/app/math.mjs", `export function add(a, b) { return a + b; }` ); await filesystem.writeFile( "/app/greet.mjs", `export function greet(name) { return "hello, " + name; }` ); const runtime = new NodeRuntime({ systemDriver: createNodeDriver({ filesystem, permissions: { ...allowAllFs }, }), runtimeDriverFactory: createNodeRuntimeDriverFactory(), }); const result = await runtime.run<{ sum: number; greeting: string }>( ` import { add } from "./math.mjs"; import { greet } from "./greet.mjs"; export const sum = add(1, 2); ``` -------------------------------- ### ProjectCompilerOptions Source: https://secureexec.dev/docs/api-reference Options for compiling a project, including the working directory and the path to the configuration file. ```typescript { cwd?: string; configFilePath?: string; } ``` -------------------------------- ### VirtualFileSystem Interface Source: https://secureexec.dev/docs/api-reference Provides methods for interacting with the virtual file system, including reading, writing, and managing files and directories. ```APIDOC ## VirtualFileSystem Interface ### Methods - **readFile(path)**: Reads a file as bytes. Returns `Promise`. - **readTextFile(path)**: Reads a file as text. Returns `Promise`. - **readDir(path)**: Lists directory entries. Returns `Promise`. - **readDirWithTypes(path)**: Lists directory entries with type information. Returns `Promise`. - **writeFile(path, content)**: Writes content to a file. Returns `Promise`. - **createDir(path)**: Creates a directory. Returns `Promise`. - **mkdir(path)**: Creates a directory (alias). Returns `Promise`. - **exists(path)**: Checks if a path exists. Returns `Promise`. - **stat(path)**: Gets file metadata. Returns `Promise`. - **removeFile(path)**: Deletes a file. Returns `Promise`. - **removeDir(path)**: Deletes a directory. Returns `Promise`. - **rename(old, new)**: Renames a file or directory. Returns `Promise`. ``` -------------------------------- ### Allow All Permissions Source: https://secureexec.dev/docs/system-drivers/node Use built-in helpers to grant all permissions for development or trusted environments. This includes filesystem, network, child process, and environment access. ```typescript import { allowAllFs, allowAllNetwork, allowAllChildProcess, allowAllEnv, allowAll } from "secure-exec"; const driver = createNodeDriver({ permissions: { ...allowAllFs, ...allowAllNetwork }, }); // Or allow everything: const permissive = createNodeDriver({ permissions: allowAll }); ``` -------------------------------- ### runtime.run() Source: https://secureexec.dev/docs/api-reference Evaluates code and returns the sandbox module's exports. Use when the sandbox should compute and return a value. ```APIDOC ## runtime.run() ### Description Evaluates code as export-based evaluation. Returns the sandbox module's exports. Use when the sandbox should compute and return a value. ### Signature ```ts run(code: string, filePath?: string): Promise> ``` ``` -------------------------------- ### Instantiate NodeRuntime Source: https://secureexec.dev/docs/api-reference Create a new NodeRuntime instance with required system and runtime drivers. Optional parameters can configure memory limits, CPU time, timing mitigation, stdio hooks, and payload limits. ```typescript new NodeRuntime(options: NodeRuntimeOptions) ``` -------------------------------- ### Initialize TypeScript tools Source: https://secureexec.dev/docs/sdk-overview Creates an instance of TypeScript tools for interacting with the TypeScript compiler within the sandbox. ```typescript import { createTypeScriptTools } from "@secure-exec/typescript"; const ts = createTypeScriptTools({ systemDriver: createNodeDriver(), runtimeDriverFactory: createNodeRuntimeDriverFactory(), }); ``` -------------------------------- ### Configure Node Runtime with Memory Limit Source: https://secureexec.dev/docs/runtimes/node Shows how to pass options to createNodeRuntime() to configure V8 isolate behavior, specifically setting a memory limit. ```typescript await kernel.mount(createNodeRuntime({ memoryLimit: 128, // 128 MB per isolate })); ``` -------------------------------- ### Create a system driver with only filesystem access Source: https://secureexec.dev/docs/sdk-overview Initializes a Node.js system driver that restricts all capabilities except for filesystem access, which is fully allowed. ```typescript // Allow only filesystem const fsOnly = createNodeDriver({ permissions: { fs: allowAllFs } }); ``` -------------------------------- ### createInMemoryFileSystem Source: https://secureexec.dev/docs/api-reference Creates a virtual filesystem that is entirely managed in memory, utilizing Maps for storage. ```APIDOC ## `createInMemoryFileSystem()` ### Description Creates a fully in-memory filesystem backed by Maps. ### Method `createInMemoryFileSystem(): InMemoryFileSystem` ``` -------------------------------- ### Create a runtime with resource limits Source: https://secureexec.dev/docs/sdk-overview Initializes a NodeRuntime with specified memory and CPU time limits. This helps prevent runaway execution by bounding resource consumption. ```typescript const runtime = new NodeRuntime({ systemDriver: createNodeDriver(), runtimeDriverFactory: createNodeRuntimeDriverFactory(), memoryLimit: 64, // MB cpuTimeLimitMs: 5000, }); ```