> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentfront.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Secure Code Execution with Enclave

> Execute untrusted JavaScript safely using Enclave's defense-in-depth security model combining AST validation, code transformation, and runtime sandboxing.

Enclave is FrontMCP's secure execution environment for running untrusted JavaScript code. It provides a defense-in-depth security model that combines AST validation (via ast-guard), code transformation, and runtime sandboxing to safely execute model-generated code.

<CardGroup cols={3}>
  <Card title="AST Validation" icon="shield-check">
    Block dangerous constructs before execution using ast-guard's AgentScript preset
  </Card>

  <Card title="Code Transformation" icon="arrows-rotate">
    Automatically transform code for safe execution with proxied functions and loop limits
  </Card>

  <Card title="Runtime Sandboxing" icon="lock">
    Execute in isolated Node.js vm context with controlled globals and resource limits
  </Card>
</CardGroup>

## When to Use Enclave

Enclave is designed for scenarios where you need to execute JavaScript code from untrusted sources:

* **LLM-generated code** - Execute code written by AI models safely
* **User-provided scripts** - Run user scripts in a controlled environment
* **Plugin/extension systems** - Allow third-party code to run securely
* **Workflow automation** - Execute orchestration logic with tool access

<Note>
  Enclave is used internally by the [CodeCall Plugin](/frontmcp/v/0.7/plugins/codecall-plugin) to execute JavaScript execution plans. You can also use it directly for custom use cases.
</Note>

## Installation

Enclave is available as a separate package:

<CodeGroup>
  ```bash npm theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
  npm install enclave-vm
  ```

  ```bash pnpm theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
  pnpm add enclave-vm
  ```

  ```bash yarn theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
  yarn add enclave-vm
  ```
</CodeGroup>

## Quick Start

```ts theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
import { Enclave } from 'enclave-vm';

// Create an enclave with a tool handler
const enclave = new Enclave({
  timeout: 5000, // 5 second timeout
  maxToolCalls: 50, // Max 50 tool calls
  maxIterations: 10000, // Max 10K loop iterations
  toolHandler: async (toolName, args) => {
    // Handle tool calls from the script
    console.log(`Tool called: ${toolName}`, args);
    return { result: 'data' };
  },
});

// Execute AgentScript code
const code = `
  const users = await callTool('users:list', { limit: 10 });
  const filtered = users.filter(u => u.active);
  return filtered.length;
`;

const result = await enclave.run(code);

if (result.success) {
  console.log('Result:', result.value);
  console.log('Stats:', result.stats);
} else {
  console.error('Error:', result.error);
}

// Clean up
enclave.dispose();
```

## Security Level Presets

Enclave provides pre-configured security profiles that balance functionality against risk:

```ts theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
import { Enclave } from 'enclave-vm';

// Use STRICT for untrusted AI-generated code
const strictEnclave = new Enclave({ securityLevel: 'STRICT' });

// Use STANDARD for internal tools (default)
const standardEnclave = new Enclave({ securityLevel: 'STANDARD' });

// Override specific values from the preset
const customEnclave = new Enclave({
  securityLevel: 'SECURE',
  timeout: 20000,  // Override SECURE's 15s default
});
```

### Security Level Comparison

| Setting               | STRICT | SECURE | STANDARD | PERMISSIVE |
| --------------------- | ------ | ------ | -------- | ---------- |
| timeout               | 5s     | 15s    | 30s      | 60s        |
| maxIterations         | 1,000  | 5,000  | 10,000   | 100,000    |
| maxToolCalls          | 10     | 50     | 100      | 1,000      |
| maxConsoleCalls       | 100    | 500    | 1,000    | 10,000     |
| maxConsoleOutputBytes | 64KB   | 256KB  | 1MB      | 10MB       |
| sanitizeStackTraces   | YES    | YES    | NO       | NO         |
| blockTimingAPIs       | YES    | NO     | NO       | NO         |
| allowUnboundedLoops   | NO     | NO     | YES      | YES        |
| unicodeSecurityCheck  | YES    | YES    | NO       | NO         |

<Warning>
  Use `STRICT` for any untrusted code, including AI-generated scripts from external sources or user-submitted scripts.
</Warning>

***

## Defense-in-Depth Security Model

Enclave uses a four-layer security approach:

### Layer 1: AST Validation

Before any code runs, Enclave validates the AST using ast-guard's AgentScript preset:

```ts theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
// These are automatically blocked:
eval('code');                    // ❌ eval blocked
new Function('return 1')();       // ❌ Function constructor blocked
setTimeout(() => {}, 100);        // ❌ setTimeout blocked
process.exit();                   // ❌ process access blocked
window.location;                  // ❌ window access blocked
this.constructor;                 // ❌ this access blocked
```

The AgentScript preset blocks:

| Category                   | Blocked Constructs                                                 |
| -------------------------- | ------------------------------------------------------------------ |
| **Eval-like**              | `eval`, `Function`, `setTimeout`, `setInterval`                    |
| **Globals**                | `process`, `require`, `window`, `document`, `global`, `globalThis` |
| **Context access**         | `this`, `self`, `parent`, `top`, `frames`                          |
| **Prototype manipulation** | `__proto__`, `constructor`, `prototype` access                     |

### Layer 2: Code Transformation

Valid code is transformed for safe execution:

```ts theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
// Original code:
const users = await callTool('users:list', {});
for (const user of users) {
  console.log(user.name);
}

// Transformed code:
async function __ag_main() {
  const users = await __safe_callTool('users:list', {});
  __safe_forOf(users, (user) => {
    __safe_console.log(user.name);
  });
}
```

Transformations include:

* **Main wrapper**: Wrap code in `async function __ag_main()` for top-level await
* **Safe callTool**: Transform `callTool` → `__safe_callTool` (proxied through Enclave)
* **Safe loops**: Transform `for`, `while`, `do-while` → safe versions with iteration limits
* **Safe console**: Transform `console` → `__safe_console` (captured for logging with rate limiting)

### Layer 3: Runtime Sandboxing

Code executes in an isolated Node.js vm context:

* **Isolated context**: Fresh context with no access to host environment
* **Controlled globals**: Only whitelisted globals available (`Math`, `JSON`, `Array`, etc.)
* **Resource limits**: Timeout, iteration count, tool call limits, and console rate limits enforced
* **Stack sanitization**: Error stack traces sanitized to prevent information leakage

### Layer 4: Reference Sidecar (Optional)

When enabled, large data is handled separately:

* **Large data extraction**: Strings exceeding the threshold are stored in sidecar storage
* **Reference tokens**: Large strings are replaced with safe reference tokens (`__ref_abc123`)
* **Lazy resolution**: Data is only resolved when explicitly accessed
* **Composite blocking**: String concatenation with references can be blocked (`allowComposites: false`)

## Configuration Options

<ParamField path="timeout" type="number" default="30000">
  Maximum execution time in milliseconds (default 30 seconds)
</ParamField>

<ParamField path="maxToolCalls" type="number" default="100">
  Maximum number of tool calls allowed per execution
</ParamField>

<ParamField path="maxIterations" type="number" default="10000">
  Maximum loop iterations allowed (prevents infinite loops)
</ParamField>

<ParamField path="toolHandler" type="function">
  Async function that handles `callTool()` invocations from the script.
  Signature: `(toolName: string, args: Record<string, unknown>) => Promise<unknown>`
</ParamField>

<ParamField path="globals" type="object">
  Additional globals to make available in the script context
</ParamField>

<ParamField path="validate" type="boolean" default="true">
  Whether to validate code with ast-guard before execution
</ParamField>

<ParamField path="transform" type="boolean" default="true">
  Whether to transform code before execution
</ParamField>

<ParamField path="allowFunctionsInGlobals" type="boolean" default="false">
  Allow functions in the `globals` object. Required when providing callback functions or utilities.
</ParamField>

<ParamField path="maxConsoleOutputBytes" type="number">
  Maximum total console output in bytes. Prevents I/O flood attacks via excessive logging.
  Defaults vary by security level: STRICT=64KB, SECURE=256KB, STANDARD=1MB, PERMISSIVE=10MB.
</ParamField>

<ParamField path="maxConsoleCalls" type="number">
  Maximum number of console calls allowed. Prevents I/O flood attacks via rapid-fire logging.
  Defaults vary by security level: STRICT=100, SECURE=500, STANDARD=1000, PERMISSIVE=10000.
</ParamField>

<ParamField path="sidecar" type="object">
  Configuration for handling large data via reference tokens

  <Expandable title="properties">
    <ResponseField name="enabled" type="boolean" default="false">
      Enable the sidecar feature for large data handling
    </ResponseField>

    <ResponseField name="maxTotalSize" type="number" default="10485760">
      Maximum total size of all stored references in bytes (default 10MB)
    </ResponseField>

    <ResponseField name="maxReferenceSize" type="number" default="1048576">
      Maximum size of a single reference in bytes (default 1MB)
    </ResponseField>

    <ResponseField name="extractionThreshold" type="number" default="1024">
      Minimum string size to extract to sidecar. Smaller strings stay inline.
    </ResponseField>

    <ResponseField name="maxResolvedSize" type="number" default="5242880">
      Maximum size when resolving references (default 5MB)
    </ResponseField>

    <ResponseField name="allowComposites" type="boolean" default="false">
      Allow string concatenation with reference tokens. Keep `false` for security.
    </ResponseField>
  </Expandable>
</ParamField>

## Reference Sidecar

The sidecar is a powerful feature for handling large data in AgentScript without embedding it in the script. This keeps script size small for reliable AST validation while allowing tools to return large datasets.

### How It Works

1. **Extraction**: When a tool returns data with large strings (> `extractionThreshold`), those strings are stored in the sidecar and replaced with reference tokens (`__ref_abc123`)
2. **Lazy Resolution**: When script code accesses a reference token, it's resolved just-in-time to the actual data
3. **Safe Property Access**: Only explicit property accesses trigger resolution, preventing data exfiltration

```ts theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
const enclave = new Enclave({
  toolHandler: async (name, args) => {
    if (name === 'documents:get') {
      // Returns a 2MB document - automatically stored in sidecar
      return { content: '...2MB of text...' };
    }
  },
  sidecar: {
    enabled: true,
    extractionThreshold: 1024,    // Extract strings > 1KB
    allowComposites: false,        // Block: ref + "_suffix" (security)
  },
});

const result = await enclave.run(`
  const doc = await callTool('documents:get', { id: 'doc-123' });
  // doc.content is a reference token, resolved on access
  return { wordCount: doc.content.split(' ').length };
`);
```

### Security: allowComposites

The `allowComposites: false` setting (default) blocks string concatenation with reference tokens:

```js theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
// When allowComposites: false (default, secure)
const result = ref + "_suffix";  // ❌ BLOCKED - prevents prototype pollution

// When allowComposites: true (less secure)
const result = ref + "_suffix";  // ✅ ALLOWED - use with caution
```

Keep `allowComposites: false` unless you specifically need string concatenation with large data.

## AI Scoring Gate

The Scoring Gate adds semantic security analysis that detects attack patterns beyond static AST validation:

* **Data exfiltration** - list→send or query→export sequences
* **Excessive access** - High limits, wildcard queries
* **Fan-out attacks** - Tool calls inside loops
* **Sensitive data access** - Passwords, tokens, PII fields

```ts theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
import { Enclave } from 'enclave-vm';

// Rule-based scorer (~1ms latency, zero dependencies)
const enclave = new Enclave({
  scoringGate: {
    scorer: 'rule-based',
    blockThreshold: 70,     // Score >= 70 blocks execution
    warnThreshold: 40,      // Score >= 40 logs warning
    failOpen: true,         // Allow if scoring fails (default)
  },
});

// External API scorer (best detection, ~100ms latency)
const enclaveWithApi = new Enclave({
  scoringGate: {
    scorer: 'external-api',
    externalApi: {
      endpoint: 'https://api.example.com/score',
      apiKey: process.env.SCORING_API_KEY,
      timeoutMs: 5000,
      retries: 1,
    },
  },
});
```

### Scorer Types

| Type           | Latency  | Dependencies   | Detection |
| -------------- | -------- | -------------- | --------- |
| `disabled`     | 0ms      | None           | None      |
| `rule-based`   | \~1ms    | None           | Good      |
| `local-llm`    | \~5-10ms | Model download | Better    |
| `external-api` | \~100ms  | Network        | Best      |

### Detection Rules

The rule-based scorer detects these patterns:

| Rule              | Score | Description                            |
| ----------------- | ----- | -------------------------------------- |
| `SENSITIVE_FIELD` | 35    | Queries password/token/secret fields   |
| `EXCESSIVE_LIMIT` | 25    | limit > 10,000                         |
| `WILDCARD_QUERY`  | 20    | query="\*" or filter={}                |
| `LOOP_TOOL_CALL`  | 25    | callTool inside for/for-of loop        |
| `EXFIL_PATTERN`   | 50    | list→send or query→export sequence     |
| `EXTREME_VALUE`   | 30    | Numeric arg > 1,000,000                |
| `DYNAMIC_TOOL`    | 20    | Variable tool name (not static string) |
| `BULK_OPERATION`  | 15    | Tool name contains bulk/batch/all      |

### Caching

Results are cached by code hash (default: 5 minutes, 1000 entries):

```ts theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
const enclave = new Enclave({
  scoringGate: {
    scorer: 'rule-based',
    cache: {
      enabled: true,
      ttlMs: 300000,    // 5 minutes
      maxEntries: 1000,
    },
  },
});
```

***

## Worker Pool Adapter

For OS-level memory isolation, use the worker threads adapter:

```ts theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
import { Enclave } from 'enclave-vm';

const enclave = new Enclave({
  adapter: 'worker_threads',
  workerPoolConfig: {
    minWorkers: 2,
    maxWorkers: 8,
    memoryLimitPerWorker: 256 * 1024 * 1024, // 256MB
  },
});
```

### Worker Pool Features

* **Pool management** - Auto-scaling with min/max workers
* **Memory monitoring** - Workers recycled when exceeding limits
* **Hard halt** - Force terminate via `worker.terminate()`
* **Rate limiting** - Message flood protection
* **Dual-layer sandbox** - Worker thread + VM context isolation

### Worker Pool Presets

| Setting                | STRICT | SECURE | STANDARD | PERMISSIVE |
| ---------------------- | ------ | ------ | -------- | ---------- |
| maxWorkers             | 4      | 8      | 16       | 32         |
| memoryLimitPerWorker   | 64MB   | 128MB  | 256MB    | 512MB      |
| maxExecutionsPerWorker | 100    | 500    | 1,000    | 5,000      |
| maxQueueSize           | 20     | 50     | 100      | 500        |
| maxMessagesPerSecond   | 100    | 500    | 1,000    | 5,000      |

### Worker Pool Configuration

<ParamField path="workerPoolConfig.minWorkers" type="number" default="2">
  Minimum warm workers to keep in the pool
</ParamField>

<ParamField path="workerPoolConfig.maxWorkers" type="number" default="os.cpus().length">
  Maximum workers in the pool
</ParamField>

<ParamField path="workerPoolConfig.memoryLimitPerWorker" type="number" default="128MB">
  Memory limit per worker (workers exceeding this are recycled)
</ParamField>

<ParamField path="workerPoolConfig.maxExecutionsPerWorker" type="number" default="1000">
  Executions before a worker is recycled (prevents memory leaks)
</ParamField>

<ParamField path="workerPoolConfig.maxQueueSize" type="number" default="100">
  Maximum pending executions in the queue
</ParamField>

<ParamField path="workerPoolConfig.maxMessagesPerSecond" type="number" default="1000">
  Rate limit for messages from a single worker (prevents flooding)
</ParamField>

***

## Execution Results

Enclave returns a structured result with success/error status and execution stats:

```ts theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
interface ExecutionResult<T> {
  success: boolean;
  value?: T;              // Result value (if success)
  error?: {               // Error details (if failed)
    name: string;
    message: string;
    code: string;
    stack?: string;
  };
  stats: {
    duration: number;      // Execution time in ms
    toolCallCount: number; // Number of tool calls made
    iterationCount: number; // Number of loop iterations
  };
}
```

### Error Codes

| Code               | Meaning                    | Action                                |
| ------------------ | -------------------------- | ------------------------------------- |
| `VALIDATION_ERROR` | AST validation failed      | Fix the code - blocked construct used |
| `EXECUTION_ERROR`  | Runtime error in script    | Fix script logic                      |
| `TIMEOUT`          | Execution exceeded timeout | Optimize or increase timeout          |
| `TOOL_ERROR`       | Tool call failed           | Check tool input/availability         |

## Advanced Usage

### Custom Globals

Provide custom globals for scripts to access:

```ts theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
const enclave = new Enclave({
  toolHandler: async (name, args) => { /* ... */ },
  globals: {
    // Custom read-only context
    context: {
      userId: 'user-123',
      tenantId: 'tenant-456',
    },
    // Custom utility function
    formatDate: (date: Date) => date.toISOString(),
  },
});

const code = `
  const userId = context.userId;
  const timestamp = formatDate(new Date());
  return { userId, timestamp };
`;

const result = await enclave.run(code);
```

### One-Shot Execution

For simple cases, use the convenience function:

```ts theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
import { runAgentScript } from 'enclave-vm';

const result = await runAgentScript(`
  return Math.max(1, 2, 3);
`, {
  timeout: 1000,
});

console.log(result.value); // 3
```

### Tool Handler Integration

Integrate with your existing tool system:

```ts theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
import { Enclave } from 'enclave-vm';
import { ToolRegistry } from './tools';

const enclave = new Enclave({
  timeout: 10000,
  toolHandler: async (toolName, args) => {
    // Look up tool in registry
    const tool = ToolRegistry.get(toolName);
    if (!tool) {
      throw new Error(`Unknown tool: ${toolName}`);
    }

    // Execute with your pipeline (auth, logging, etc.)
    return tool.execute(args);
  },
});
```

## Security Considerations

<Warning>
  While Enclave provides strong security guarantees, it should be used as part of a defense-in-depth strategy. Always:

  * Validate tool inputs before execution
  * Limit what tools are available to scripts
  * Monitor execution for anomalies
  * Keep Enclave and ast-guard updated
</Warning>

### What Enclave Protects Against

* **Code injection** - Blocked by AST validation
* **Infinite loops** - Limited by `maxIterations`
* **Resource exhaustion** - Limited by `timeout` and `maxToolCalls`
* **I/O flood attacks** - Limited by `maxConsoleOutputBytes` and `maxConsoleCalls`
* **Global access** - Blocked by AST validation and isolated context
* **Prototype pollution** - Blocked by AST validation
* **Information leakage** - Stack traces sanitized

### What Enclave Does NOT Protect Against

* **Tool abuse** - Scripts can call allowed tools; limit what's available
* **Algorithmic complexity** - Scripts can run O(n²) algorithms within limits
* **Memory exhaustion** - Large arrays/objects within timeout
* **Side effects** - Tool calls have real effects; use read-only tools where possible

## Integration with CodeCall

The [CodeCall Plugin](/frontmcp/v/0.7/plugins/codecall-plugin) uses Enclave internally:

```ts theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
// CodeCall plugin configuration maps to Enclave
CodeCallPlugin.init({
  enclave: {
    timeoutMs: 5000,
    maxToolCalls: 100,
    maxIterations: 10000,
    allowConsole: true,
  },
});

// Equivalent to:
new Enclave({
  timeout: 5000,
  maxToolCalls: 100,
  maxIterations: 10000,
  globals: {
    console: { log: ..., warn: ..., error: ... },
  },
});
```

## Resources

<CardGroup cols={2}>
  <Card title="AST Guard Guide" icon="shield-check" href="/frontmcp/v/0.7/guides/ast-guard">
    Learn about ast-guard's validation rules and presets
  </Card>

  <Card title="CodeCall Plugin" icon="code" href="/frontmcp/v/0.7/plugins/codecall-plugin">
    See Enclave in action with the CodeCall plugin
  </Card>

  <Card title="Source Code" icon="github" href="https://github.com/agentfront/enclave/tree/main/libs/enclave">
    View the Enclave source code
  </Card>

  <Card title="Security Audit" icon="file-shield" href="https://github.com/agentfront/enclave/blob/main/libs/enclave/SECURITY-AUDIT.md">
    Review the security audit documentation
  </Card>
</CardGroup>
