Skip to main content

Overview

The @tinyclaw/sandbox package provides lightweight sandboxed JavaScript/TypeScript code execution for Tiny Claw using Bun Worker threads. It offers sub-millisecond boot time, minimal memory overhead, and a multi-layered security model.

Why Bun Workers?

FeatureDocker (mrcloudchase)Bun Workers (Tiny Claw)
Boot time1-3 seconds<1ms
Memory overhead~50MB per container~1MB per worker
DependencyDocker daemon requiredNone — built into Bun
PortabilityLinux/Mac (daemon)Everywhere Bun runs
TeardownContainer cleanupWorker.terminate()

Security Model

  • process, require, and Bun globals are blocked
  • fetch/WebSocket blocked by default (controllable via allowNet)
  • Filesystem access blocked by default (controllable via allowFs)
  • Configurable timeout with hard kill (default: 10s, max: 30s)
  • Each execution runs in a fresh worker (no state leakage)

Installation

bun add @tinyclaw/sandbox

Usage

Basic Execution

import { createSandbox } from '@tinyclaw/sandbox';

const sandbox = createSandbox();

const result = await sandbox.execute(`
  return 2 + 2;
`);

console.log(result.output); // "4"
console.log(result.success); // true
console.log(result.durationMs); // &lt;1

Execution with Input

const result = await sandbox.executeWithInput(
  `
    return input.numbers.reduce((sum, n) => sum + n, 0);
  `,
  { numbers: [1, 2, 3, 4, 5] }
);

console.log(result.output); // "15"

Configuration Options

const result = await sandbox.execute(
  `
    const response = await fetch('https://api.example.com/data');
    return await response.json();
  `,
  {
    timeoutMs: 5000,      // 5 second timeout
    allowNet: true,        // Enable network access
    allowFs: false,        // Keep filesystem blocked
  }
);

Cleanup

// Terminate all active workers
sandbox.shutdown();

API Reference

createSandbox()

Creates a new sandbox instance. Returns: Sandbox

Sandbox

Sandbox instance for executing code in isolation.

execute(code, config?)

Execute JavaScript/TypeScript code in a sandboxed environment.
code
string
required
The code to execute. Can use await for async operations.
config
SandboxConfig
Execution configuration options.
config.timeoutMs
number
default:"10000"
Execution timeout in milliseconds. Maximum: 30000 (30 seconds).
config.allowNet
boolean
default:"false"
Allow network access (fetch, WebSocket).
config.allowFs
boolean
default:"false"
Allow filesystem access.
result
Promise<SandboxResult>
Execution result containing output, status, and timing information.

executeWithInput(code, input, config?)

Execute code with input data accessible via the input variable.
code
string
required
The code to execute.
input
unknown
required
Data to pass to the sandbox (available as input variable).
config
SandboxConfig
Execution configuration options (same as execute).
result
Promise<SandboxResult>
Execution result.

shutdown()

Terminate all running workers and clean up resources.

SandboxResult

Result object returned by execution methods.
success
boolean
Whether the code executed successfully without errors or timeout.
output
string
The return value of the code (stringified).
error
string | undefined
Error message if execution failed.
durationMs
number
Execution time in milliseconds.

Error Handling

const result = await sandbox.execute(
  `
    throw new Error('Something went wrong');
  `
);

if (!result.success) {
  console.error('Execution failed:', result.error);
  console.log('Duration:', result.durationMs, 'ms');
}

Timeout Behavior

const result = await sandbox.execute(
  `
    // Infinite loop
    while (true) {}
  `,
  { timeoutMs: 1000 }
);

console.log(result.success); // false
console.log(result.error); // "Execution timeout after 1000ms (hard kill)"

Security Restrictions

The following operations are blocked in the sandbox:
// ❌ Blocked: Process access
process.exit(1);

// ❌ Blocked: Bun runtime
Bun.write('file.txt', 'data');

// ❌ Blocked: require() (unless explicitly enabled)
const fs = require('fs');

// ❌ Blocked: Network access (unless allowNet: true)
await fetch('https://example.com');

// ❌ Blocked: __dirname and __filename
console.log(__dirname);