Skip to main content
API reference for the @enclave-vm/ast package.

Installation

npm install @enclave-vm/ast

JSAstValidator Class

Main AST validation class.

Constructor

new JSAstValidator(preset: ValidationPreset)

Methods

validate(code)

Validate JavaScript code against the preset rules.
async validate(code: string): Promise<ValidationResult>
Returns: ValidationResult
interface ValidationResult {
  valid: boolean;
  issues: ValidationIssue[];
  ast?: ESTree.Program;
}

interface ValidationIssue {
  rule: string;
  message: string;
  severity: 'error' | 'warning' | 'info';
  location?: {
    line: number;
    column: number;
    endLine?: number;
    endColumn?: number;
  };
  fix?: {
    range: [number, number];
    text: string;
  };
}
Example:
import { JSAstValidator, createAgentScriptPreset } from '@enclave-vm/ast';

const validator = new JSAstValidator(createAgentScriptPreset());
const result = await validator.validate(`
  const x = eval('code');
`);

if (!result.valid) {
  for (const issue of result.issues) {
    console.log(`${issue.rule}: ${issue.message}`);
  }
}

PreScanner Class

Fast pre-scanning for DoS protection.

Constructor

new PreScanner(config: PreScannerConfig)

Methods

scan(code)

Scan code for potential issues before parsing.
scan(code: string): PreScanResult
Returns: PreScanResult
interface PreScanResult {
  valid: boolean;
  issues: PreScanIssue[];
}

interface PreScanIssue {
  message: string;
  severity: 'error' | 'warning';
}
Example:
import { PreScanner, createPreScannerConfig } from '@enclave-vm/ast';

const scanner = new PreScanner(createPreScannerConfig('agentscript'));
const result = scanner.scan(code);

if (!result.valid) {
  console.log('Pre-scan failed:', result.issues);
}

Factory Functions

createAgentScriptPreset(options?)

Create the AgentScript validation preset.
function createAgentScriptPreset(options?: AgentScriptOptions): ValidationPreset
Options:
interface AgentScriptOptions {
  // Globals
  allowedGlobals?: string[];
  additionalDisallowedIdentifiers?: string[];

  // Features
  requireCallTool?: boolean;

  // Loops
  allowedLoops?: {
    allowFor?: boolean;
    allowForOf?: boolean;
    allowWhile?: boolean;
    allowDoWhile?: boolean;
    allowForIn?: boolean;
  };

  // Functions
  allowArrowFunctions?: boolean;
  allowFunctionDeclarations?: boolean;
}
Example:
const preset = createAgentScriptPreset({
  allowedGlobals: ['callTool', 'Math', 'JSON', 'console', 'context'],
  allowedLoops: {
    allowFor: true,
    allowForOf: true,
    allowWhile: false,
  },
});

createPreScannerConfig(preset)

Create pre-scanner configuration.
function createPreScannerConfig(preset: 'agentscript' | 'standard'): PreScannerConfig
PreScannerConfig:
interface PreScannerConfig {
  maxInputSize: number;
  maxNestingDepth: number;
  maxStringLength: number;
  maxArrayLiteralLength: number;
  checkReDoS: boolean;
  blockedPatterns: RegExp[];
}

createSecurityRules()

Get all built-in security rules.
function createSecurityRules(): ValidationRule[]

ValidationPreset

interface ValidationPreset {
  rules: ValidationRule[];
  globals: GlobalConfig;
  transforms?: TransformConfig[];
}

interface GlobalConfig {
  allowed: string[];
  disallowed: string[];
}

ValidationRule

interface ValidationRule {
  id: string;
  name: string;
  description: string;
  severity: 'error' | 'warning' | 'info';
  check: (node: ESTree.Node, context: RuleContext) => void;
}

interface RuleContext {
  report: (issue: Omit<ValidationIssue, 'rule'>) => void;
  getSource: () => string;
  getAncestors: () => ESTree.Node[];
}

Built-in Rules

Rule IDDescription
no-evalBlock eval() and Function()
no-dynamic-codeBlock setTimeout/setInterval with strings
no-system-accessBlock process, require, import
no-global-accessBlock window, global, globalThis
no-prototype-accessBlock proto, constructor
no-metaprogrammingBlock Proxy, Reflect
no-networkBlock fetch, XMLHttpRequest, WebSocket
no-storageBlock localStorage, sessionStorage
no-native-codeBlock WebAssembly, Worker
no-thisBlock this keyword
no-user-functionsBlock function declarations
no-unbounded-loopsBlock while, do-while
no-for-inBlock for-in loops
allowed-globals-onlyOnly allow specified globals
static-tool-callsRequire string literals for tool names
bounded-iterationsEnforce iteration limits

Code Transformation

transformAgentScript(code, options)

Transform code for safe execution.
function transformAgentScript(
  code: string,
  options?: TransformOptions
): string
Options:
interface TransformOptions {
  wrapInMain?: boolean;
  transformCallTool?: boolean;
  transformLoops?: boolean;
  transformConsole?: boolean;
}
Example:
import { transformAgentScript } from '@enclave-vm/ast';

const transformed = transformAgentScript(`
  const users = await callTool('users:list', {});
  for (const user of users) {
    console.log(user.name);
  }
  return users.length;
`, {
  wrapInMain: true,
  transformCallTool: true,
  transformLoops: true,
});

// Output:
// async function __ag_main() {
//   const users = await __safe_callTool('users:list', {});
//   for (const user of __safe_forOf(users)) {
//     __safe_console.log(user.name);
//   }
//   return users.length;
// }

Custom Rules

Creating a Custom Rule

import { ValidationRule, RuleContext } from '@enclave-vm/ast';

const noConsoleRule: ValidationRule = {
  id: 'no-console',
  name: 'No Console',
  description: 'Disallow console statements',
  severity: 'warning',

  check(node, context) {
    if (
      node.type === 'CallExpression' &&
      node.callee.type === 'MemberExpression' &&
      node.callee.object.type === 'Identifier' &&
      node.callee.object.name === 'console'
    ) {
      context.report({
        message: 'Console statements are not allowed',
        severity: 'warning',
        location: {
          line: node.loc?.start.line || 0,
          column: node.loc?.start.column || 0,
        },
      });
    }
  },
};

Using Custom Rules

import { JSAstValidator, createAgentScriptPreset } from '@enclave-vm/ast';

const preset = createAgentScriptPreset();
preset.rules.push(noConsoleRule);

const validator = new JSAstValidator(preset);

Complete Example

import {
  JSAstValidator,
  PreScanner,
  createAgentScriptPreset,
  createPreScannerConfig,
  transformAgentScript,
} from '@enclave-vm/ast';

async function validateAndTransform(code: string) {
  // Step 1: Pre-scan
  const scanner = new PreScanner(createPreScannerConfig('agentscript'));
  const scanResult = scanner.scan(code);

  if (!scanResult.valid) {
    return { valid: false, error: 'Pre-scan failed', issues: scanResult.issues };
  }

  // Step 2: AST validation
  const preset = createAgentScriptPreset({
    allowedGlobals: ['callTool', 'Math', 'JSON', 'console'],
  });
  const validator = new JSAstValidator(preset);
  const validation = await validator.validate(code);

  if (!validation.valid) {
    return { valid: false, error: 'Validation failed', issues: validation.issues };
  }

  // Step 3: Transform
  const transformed = transformAgentScript(code, {
    wrapInMain: true,
    transformCallTool: true,
    transformLoops: true,
  });

  return { valid: true, code: transformed };
}

// Usage
const result = await validateAndTransform(`
  const users = await callTool('users:list', { limit: 10 });
  return users.length;
`);

if (result.valid) {
  console.log('Transformed code:', result.code);
} else {
  console.log('Validation errors:', result.issues);
}