---
title: Security model
description: Sandbox SDK uses VM-level isolation, input validation, and network controls to run untrusted code safely.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/sandbox/llms.txt  
> Use this file to discover all available pages before exploring further.

[Skip to content](#%5Ftop) 

# Security model

The Sandbox SDK is built on [Containers](https://developers.cloudflare.com/containers/), which run each sandbox in its own VM for strong isolation.

## Container isolation

Each sandbox runs in a separate VM, providing complete isolation:

* **Filesystem isolation** \- Sandboxes cannot access other sandboxes' files
* **Process isolation** \- Processes in one sandbox cannot see or affect others
* **Network isolation** \- Sandboxes have separate network stacks
* **Resource limits** \- CPU, memory, and disk quotas are enforced per sandbox

For complete security details about the underlying container platform, see [Containers architecture](https://developers.cloudflare.com/containers/platform-details/architecture/).

## Within a sandbox

All code within a single sandbox shares resources:

* **Filesystem** \- All processes see the same files
* **Processes** \- All sessions can see all processes
* **Network** \- Processes can communicate via localhost

For complete isolation, use separate sandboxes per user:

TypeScript

```

// Good - Each user in separate sandbox

const userSandbox = getSandbox(env.Sandbox, `user-${userId}`);


// Bad - Users sharing one sandbox

const shared = getSandbox(env.Sandbox, 'shared');

// Users can read each other's files!


```

## Input validation

### Command injection

Always validate user input before using it in commands:

TypeScript

```

// Dangerous - user input directly in command

const filename = userInput;

await sandbox.exec(`cat ${filename}`);

// User could input: "file.txt; rm -rf /"


// Safe - validate input

const filename = userInput.replace(/[^a-zA-Z0-9._-]/g, '');

await sandbox.exec(`cat ${filename}`);


// Better - use file API

await sandbox.writeFile('/tmp/input', userInput);

await sandbox.exec('cat /tmp/input');


```

## Authentication

### Sandbox access

Sandbox IDs provide basic access control but aren't cryptographically secure. Add application-level authentication:

TypeScript

```

export default {

  async fetch(request: Request, env: Env): Promise<Response> {

    const userId = await authenticate(request);

    if (!userId) {

      return new Response('Unauthorized', { status: 401 });

    }


    // User can only access their sandbox

    const sandbox = getSandbox(env.Sandbox, userId);

    return Response.json({ authorized: true });

  }

};


```

### Preview URLs

Preview URLs include randomly generated tokens. Anyone with the URL can access the service.

To revoke access, unexpose the port:

TypeScript

```

await sandbox.unexposePort(8080);


```

Python

```

from flask import Flask, request, abort

import os


app = Flask(__name__)


def check_auth():

    token = request.headers.get('Authorization')

    if token != f"Bearer {os.environ['AUTH_TOKEN']}":

        abort(401)


@app.route('/api/data')

def get_data():

    check_auth()

    return {'data': 'protected'}


```

## Secrets management

Use environment variables, not hardcoded secrets:

TypeScript

```

// Bad - hardcoded in file

await sandbox.writeFile('/workspace/config.js', `

  const API_KEY = 'sk_live_abc123';

`);


// Good - use environment variables

await sandbox.startProcess('node app.js', {

  env: {

    API_KEY: env.API_KEY,  // From Worker environment binding

  }

});


```

Clean up temporary sensitive data:

TypeScript

```

try {

  await sandbox.writeFile('/tmp/sensitive.txt', secretData);

  await sandbox.exec('python process.py /tmp/sensitive.txt');

} finally {

  await sandbox.deleteFile('/tmp/sensitive.txt');

}


```

## Proxying external API requests

Passing credentials directly to a sandbox — via environment variables or files — means the sandbox process holds a live credential that any code running inside it can read. A Worker proxy removes that exposure by keeping credentials exclusively in the Worker and giving the sandbox a short-lived JWT instead.

The flow works as follows:

```

Sandbox (short-lived JWT) → Worker proxy (validates JWT, injects real credentials) → External API


```

The sandbox never sees the real credential. If the JWT is compromised, it expires after a short window and cannot be reused.

This pattern is useful when accessing GitHub for private repository operations, AI services, or object storage where you want to keep credentials out of the container entirely. Refer to [Proxy requests to external APIs](https://developers.cloudflare.com/sandbox/guides/proxy-requests/) for a complete implementation.

## What the SDK protects against

* Sandbox-to-sandbox access (VM isolation)
* Resource exhaustion (enforced quotas)
* Container escapes (VM-based isolation)

## What you must implement

* Authentication and authorization
* Input validation and sanitization
* Rate limiting
* Application-level security (SQL injection, XSS, etc.)

## Best practices

**Use separate sandboxes for isolation**:

TypeScript

```

const sandbox = getSandbox(env.Sandbox, `user-${userId}`);


```

**Validate all inputs**:

TypeScript

```

const safe = input.replace(/[^a-zA-Z0-9._-]/g, '');

await sandbox.exec(`command ${safe}`);


```

**Use environment variables for secrets**:

TypeScript

```

await sandbox.startProcess('node app.js', {

  env: { API_KEY: env.API_KEY }

});


```

**Clean up temporary resources**:

TypeScript

```

try {

  const sandbox = getSandbox(env.Sandbox, sessionId);

  await sandbox.exec('npm test');

} finally {

  await sandbox.destroy();

}


```

## Related resources

* [Containers architecture](https://developers.cloudflare.com/containers/platform-details/architecture/) \- Underlying platform security
* [Sandbox lifecycle](https://developers.cloudflare.com/sandbox/concepts/sandboxes/) \- Resource management

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/sandbox/","name":"Sandbox SDK"}},{"@type":"ListItem","position":3,"item":{"@id":"/sandbox/concepts/","name":"Concepts"}},{"@type":"ListItem","position":4,"item":{"@id":"/sandbox/concepts/security/","name":"Security model"}}]}
```
