Cogitator
Deployment

Sandboxed Execution

Run untrusted code safely with Docker containers and WASM isolation.

Overview

The @cogitator-ai/sandbox package provides isolated execution for agent-generated code. It ships three backends -- Docker containers, WASM via Extism, and a native fallback -- managed through SandboxManager.

pnpm add @cogitator-ai/sandbox

SandboxManager

Initializes available executors and routes requests with automatic fallback when Docker or WASM is unavailable.

import { SandboxManager } from '@cogitator-ai/sandbox';

const sandbox = new SandboxManager({
  docker: { socketPath: '/var/run/docker.sock' },
  pool: { maxSize: 10, idleTimeoutMs: 60_000 },
  defaults: {
    timeout: 30_000,
    resources: { memory: '256m', cpus: 0.5, pidsLimit: 100 },
    network: { mode: 'none' },
  },
});

await sandbox.initialize();

const result = await sandbox.execute(
  { command: ['python3', '-c', 'print("hello from sandbox")'] },
  { type: 'docker', image: 'python:3.12-slim' }
);

if (result.success) {
  console.log(result.data.stdout);
}

await sandbox.shutdown();

DockerSandboxExecutor

Runs commands inside isolated Docker containers. Containers are created with all capabilities dropped, no-new-privileges enforced, and network disabled by default.

import { DockerSandboxExecutor } from '@cogitator-ai/sandbox';

const executor = new DockerSandboxExecutor({
  docker: { socketPath: '/var/run/docker.sock' },
  pool: { maxSize: 5, idleTimeoutMs: 60_000 },
});

await executor.connect();

const result = await executor.execute(
  { command: ['node', '-e', 'console.log(2 + 2)'], timeout: 10_000 },
  {
    type: 'docker',
    image: 'node:20-alpine',
    resources: { memory: '128m', cpus: 0.5, pidsLimit: 50 },
    network: { mode: 'none' },
  }
);

await executor.disconnect();

Security Defaults

SettingValuePurpose
CapDropALLDrop all Linux capabilities
SecurityOptno-new-privilegesPrevent privilege escalation
NetworkModenoneNo network access
PidsLimit100Prevent fork bombs

WasmSandboxExecutor

Runs code inside WASM modules via Extism. Cold start is 1-10ms (vs 1-5s for Docker) with 1-10MB memory per plugin.

import { WasmSandboxExecutor } from '@cogitator-ai/sandbox';

const executor = new WasmSandboxExecutor({ wasm: { cacheSize: 10 } });
await executor.connect();

const result = await executor.execute(
  { command: ['run'], stdin: JSON.stringify({ code: 'return 2 + 2' }) },
  { type: 'wasm', wasmModule: 'https://example.com/sandbox.wasm', wasi: true }
);

await executor.disconnect();

Modules load from URLs, local paths, or npm packages. An LRU cache avoids reloading on repeated calls.

ContainerPool

Reuses Docker containers across executions. Containers stay alive with sleep infinity and commands run via docker exec, amortizing startup cost.

import { ContainerPool } from '@cogitator-ai/sandbox';

const pool = new ContainerPool(dockerClient, {
  maxSize: 10,
  idleTimeoutMs: 120_000,
});

const container = await pool.acquire('python:3.12-slim', {
  memory: 256 * 1024 * 1024,
  cpus: 1,
  networkMode: 'none',
});

await pool.release(container);
await pool.release(container, { corrupted: true });

Releasing with corrupted: true destroys the container instead of returning it. Idle containers are cleaned up automatically.

Fallback Chain

SandboxManager falls back when a requested executor is unavailable:

  1. WASM requested -- Docker -- Native
  2. Docker requested -- Native
  3. Native -- always available, no isolation
const hasDocker = await sandbox.isDockerAvailable();
const hasWasm = await sandbox.isWasmAvailable();

On this page