Agent SDK

Sandboxing

Secure execution environments for agent tools and code

Sandboxing

Sandboxing is the most effective defense against prompt-injection-to-RCE attacks. When an agent can execute code or interact with external systems, it must do so within controlled boundaries.

Why Sandboxing?

Without sandboxing:

User input → Prompt injection → Agent calls code_exec → rm -rf / → 💀

With sandboxing:

User input → Prompt injection → Agent calls code_exec → Sandboxed → No effect → ✅

The fundamental challenge: LLMs are probabilistic. They can be tricked into performing unintended actions. Sandboxing ensures that even when the model is compromised, the blast radius is contained.

Built-in Sandbox

The SDK provides a built-in sandbox for code execution:

import { Sandbox } from 'assistme-agent-sdk'

const sandbox = Sandbox.create({
  type: 'container', // or 'microvm', 'wasm'
  limits: {
    memory: '512MB',
    cpu: '1 core',
    timeout: 30_000, // 30 seconds
    network: false,  // No network access
    filesystem: {
      read: ['/workspace'],  // Can read from workspace
      write: ['/workspace/output'], // Can write to output dir
    },
  },
})

const codeExec = Tool.create({
  name: 'code_exec',
  description: 'Execute Python code in a sandboxed environment',
  parameters: z.object({
    code: z.string(),
    language: z.enum(['python', 'javascript', 'bash']),
  }),
  execute: async ({ code, language }) => {
    return await sandbox.run(code, { language })
  },
})

Sandbox Types

Container Sandbox

Uses Docker/OCI containers for isolation. Good balance of security and compatibility.

const sandbox = Sandbox.create({
  type: 'container',
  image: 'python:3.12-slim', // Base image
  limits: {
    memory: '1GB',
    cpu: '2 cores',
    timeout: 60_000,
    network: false,
    filesystem: {
      read: ['/data'],
      write: ['/output'],
    },
  },
  // Pre-install packages
  setup: async (container) => {
    await container.exec('pip install numpy pandas matplotlib')
  },
})

MicroVM Sandbox

Uses Firecracker-style microVMs for strongest isolation. Recommended for production.

const sandbox = Sandbox.create({
  type: 'microvm',
  kernel: 'default',
  rootfs: 'python-3.12',
  limits: {
    memory: '512MB',
    vcpus: 1,
    timeout: 30_000,
    network: false,
  },
})

WASM Sandbox

Uses WebAssembly for lightweight, fast isolation. Best for simple computations.

const sandbox = Sandbox.create({
  type: 'wasm',
  runtime: 'wasmtime',
  limits: {
    memory: '256MB',
    timeout: 10_000,
    filesystem: false,
    network: false,
  },
})

Network Policies

Control network access granularly:

const sandbox = Sandbox.create({
  type: 'container',
  limits: {
    network: {
      // Allow specific domains
      allow: ['api.github.com', 'pypi.org'],
      // Block everything else
      defaultPolicy: 'deny',
      // Limit bandwidth
      maxBandwidth: '10MB/s',
      // No DNS resolution for unlisted domains
      dns: 'restricted',
    },
  },
})

Per-Agent Permissions

Different agents get different sandbox configurations:

const readOnlyAgent = new Agent({
  name: 'reader',
  tools: [
    Tool.create({
      name: 'code_exec',
      execute: async ({ code }) => {
        return await Sandbox.create({
          type: 'container',
          limits: {
            filesystem: { read: ['/data'], write: [] }, // No writes
            network: false,
            timeout: 10_000,
          },
        }).run(code)
      },
    }),
  ],
})

const fullAccessAgent = new Agent({
  name: 'developer',
  tools: [
    Tool.create({
      name: 'code_exec',
      requiresApproval: true, // Require human approval
      execute: async ({ code }) => {
        return await Sandbox.create({
          type: 'container',
          limits: {
            filesystem: { read: ['/workspace'], write: ['/workspace'] },
            network: { allow: ['api.github.com'] },
            timeout: 60_000,
          },
        }).run(code)
      },
    }),
  ],
})

Hermetic Execution

For maximum security, use hermetic (fully isolated) execution:

const sandbox = Sandbox.create({
  type: 'microvm',
  hermetic: true, // Full isolation
  limits: {
    memory: '512MB',
    vcpus: 1,
    timeout: 30_000,
    network: false,
    filesystem: false, // No host filesystem access
  },
  // Data is passed in/out through the API, not filesystem
})

const result = await sandbox.run(code, {
  language: 'python',
  stdin: inputData,    // Pass data in via stdin
  // stdout is the result
})

Hermetic execution means:

  • No network connections
  • No host filesystem access
  • No API calls from inside the sandbox
  • Full cleanup of data after execution
  • Each execution starts from a clean state

Secrets Management

Never expose secrets to sandboxed code:

// Bad: secret in the code
const result = await sandbox.run(`
  import requests
  r = requests.get('https://api.example.com', headers={'Authorization': '${SECRET}'})
`)

// Good: secret injected securely, not visible in logs or traces
const result = await sandbox.run(code, {
  env: {
    API_KEY: { secret: 'api-key-ref', expose: 'env' },
    // The secret is injected into the sandbox environment
    // but never appears in agent context, logs, or traces
  },
})

Monitoring Sandbox Usage

const sandbox = Sandbox.create({
  type: 'container',
  limits: { memory: '512MB', timeout: 30_000 },
  monitoring: {
    onResourceLimit: async (event) => {
      console.warn(`Sandbox hit ${event.resource} limit: ${event.detail}`)
    },
    onNetworkAttempt: async (event) => {
      if (!event.allowed) {
        await securityLog.write(`Blocked network attempt: ${event.destination}`)
      }
    },
  },
})

Best Practices

  1. Default to no-network, no-filesystem — Start with the most restrictive sandbox and only open access as needed.

  2. Use microVMs for production — Container escape is a real risk. MicroVMs provide hardware-level isolation.

  3. Set tight timeouts — Code execution should have short timeouts. Most legitimate code completes in seconds.

  4. Never put secrets in agent context — Secrets should be injected at the sandbox level, invisible to the agent and its logs.

  5. Clean up after each execution — Don't let state leak between sandbox runs. Each execution should start fresh.

  6. Monitor and alert on limits — Track when sandboxes hit resource limits. Repeated limit hits may indicate malicious activity.

  7. Log all sandbox executions — Every code execution should be logged with input, output, and resource usage for audit.