CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ses

Hardened JavaScript for fearless cooperation through secure execution contexts and object-capability security

Pending
Overview
Eval results
Files

tools.mddocs/

Development Tools

Source transformation and scope manipulation utilities for advanced SES use cases. These tools provide low-level access to SES's code transformation pipeline and scope management system.

Package Import

import { transforms, scopeTerminators } from 'ses/tools.js';

Capabilities

Source Transformations

Collection of source-to-source JavaScript transformation functions used internally by SES for secure code execution.

/**
 * Source transformation function signature
 * @param source - JavaScript source code to transform
 * @returns Transformed JavaScript source code
 */
type Transform = (source: string) => string;

/**
 * Object containing all available transformation functions
 */
interface TransformLibrary {
  rejectHtmlComments: Transform;
  evadeHtmlCommentTest: Transform;
  rejectImportExpressions: Transform;
  evadeImportExpressionTest: Transform;
  rejectSomeDirectEvalExpressions: Transform;
  mandatoryTransforms: Transform;
  applyTransforms: (source: string, transforms: Transform[]) => string;
}

const transforms: TransformLibrary;

Usage Examples:

import { transforms } from 'ses/tools.js';

// Reject potentially dangerous HTML comments
const safeSource = transforms.rejectHtmlComments(`
  // This would throw: <!-- comment -->
  const x = 1;
`);

// Reject dynamic import expressions for security
const secureSource = transforms.rejectImportExpressions(`
  // This would throw: import('dangerous-module')
  const y = 2;
`);

// Apply all mandatory security transforms
const mandatorySecure = transforms.mandatoryTransforms(originalSource);

// Apply custom transform pipeline
const customTransforms = [
  transforms.rejectHtmlComments,
  transforms.rejectImportExpressions
];
const processedSource = transforms.applyTransforms(originalSource, customTransforms);

Individual Transform Functions

HTML Comment Rejection

Rejects source code containing HTML-like comment syntax to prevent parser confusion.

/**
 * Reject source code containing HTML-like comments (<!-- or -->)
 * @param source - JavaScript source code to check
 * @returns Original source if safe
 * @throws SyntaxError if HTML comments found
 */
function rejectHtmlComments(source: string): string;

/**
 * Transform HTML-like comments to space-separated operators
 * @param source - JavaScript source code to transform
 * @returns Source with HTML comments converted to operators
 */
function evadeHtmlCommentTest(source: string): string;

Usage Examples:

import { transforms } from 'ses/tools.js';

try {
  // This will throw SyntaxError
  transforms.rejectHtmlComments('const x = 1; <!-- comment -->');
} catch (error) {
  console.log(error.message); // "Possible HTML comment rejected..."
}

// Evade rejection by converting to operators
const converted = transforms.evadeHtmlCommentTest('const x = 1; <!-- comment -->');
console.log(converted); // "const x = 1; < ! -- comment -- >"

Import Expression Rejection

Prevents dynamic import expressions that could bypass module system security.

/**
 * Reject source code containing dynamic import expressions
 * @param source - JavaScript source code to check
 * @returns Original source if safe
 * @throws SyntaxError if import expressions found
 */
function rejectImportExpressions(source: string): string;

/**
 * Transform import expressions to __import__ to evade rejection
 * @param source - JavaScript source code to transform
 * @returns Source with import expressions converted
 */
function evadeImportExpressionTest(source: string): string;

Usage Examples:

import { transforms } from 'ses/tools.js';

try {
  // This will throw SyntaxError  
  transforms.rejectImportExpressions("import('module').then(m => m.run())");
} catch (error) {
  console.log(error.message); // "Possible import expression rejected..."
}

// Evade rejection by renaming import
const converted = transforms.evadeImportExpressionTest("import('module')");
console.log(converted); // "__import__('module')"

Direct Eval Rejection

Heuristically rejects some direct eval expressions that cannot be properly shimmed.

/**
 * Reject source code that appears to contain direct eval expressions
 * @param source - JavaScript source code to check
 * @returns Original source if safe
 * @throws SyntaxError if direct eval expressions found
 * @note May have false positives and negatives - designed for innocent code
 */
function rejectSomeDirectEvalExpressions(source: string): string;

Usage Examples:

import { transforms } from 'ses/tools.js';

try {
  // This will throw SyntaxError
  transforms.rejectSomeDirectEvalExpressions('eval("console.log(\'hello\')")');
} catch (error) {
  console.log(error.message); // "Possible direct eval expression rejected..."
}

// This might not be caught (false negative)
const trickyEval = '(eval)("code")'; // Might pass through

Mandatory Transforms

Bundles together transforms that must always be applied for security.

/**
 * Apply all mandatory security transforms in the correct order
 * @param source - JavaScript source code to secure
 * @returns Source with all mandatory transforms applied
 * @throws SyntaxError if dangerous patterns found
 */
function mandatoryTransforms(source: string): string;

Usage Examples:

import { transforms } from 'ses/tools.js';

// Apply all security-critical transforms at once
const secureSource = transforms.mandatoryTransforms(`
  function userCode() {
    // User-provided code that needs security transforms
    return Math.random();
  }
`);

// Use in compartment
const compartment = new Compartment({
  transforms: [transforms.mandatoryTransforms],
  __options__: true
});

Transform Pipeline Application

Utility for applying multiple transforms in sequence.

/**
 * Apply a sequence of transforms to source code
 * @param source - Initial JavaScript source code
 * @param transforms - Array of transform functions to apply in order
 * @returns Source with all transforms applied sequentially
 */
function applyTransforms(source: string, transforms: Transform[]): string;

Usage Examples:

import { transforms } from 'ses/tools.js';

// Custom transform pipeline
const myTransforms = [
  transforms.rejectHtmlComments,
  transforms.rejectImportExpressions,
  (source) => source.replace(/console\.log/g, '/* console.log */')
];

const processedSource = transforms.applyTransforms(originalSource, myTransforms);

// Use in compartment
const compartment = new Compartment({
  transforms: myTransforms,
  __options__: true
});

Scope Terminators

Utilities for managing scope boundaries and global object behavior in different execution modes.

/**
 * Scope termination utilities for controlling variable scoping behavior
 */
interface ScopeTerminatorLibrary {
  /** Scope terminator for strict mode execution */
  strictScopeTerminator: any;
  
  /** Factory function for creating sloppy mode scope terminators */
  createSloppyGlobalsScopeTerminator: () => any;
}

const scopeTerminators: ScopeTerminatorLibrary;

Usage Examples:

import { scopeTerminators } from 'ses/tools.js';

const { strictScopeTerminator, createSloppyGlobalsScopeTerminator } = scopeTerminators;

// Access strict mode scope terminator
const strictTerminator = strictScopeTerminator;

// Create sloppy mode scope terminator
const sloppyTerminator = createSloppyGlobalsScopeTerminator();

// These are typically used internally by SES's evaluation system
// but can be accessed for advanced use cases involving custom
// evaluation contexts and scope management

Integration with Compartments

Using transforms in compartment creation for custom code processing:

import 'ses';
import { transforms } from 'ses/tools.js';

lockdown();

// Create compartment with security transforms
const secureCompartment = new Compartment({
  transforms: [transforms.mandatoryTransforms],
  globals: { console: harden(console) },
  __options__: true
});

// Create compartment with custom transform pipeline
const customCompartment = new Compartment({
  transforms: [
    transforms.rejectHtmlComments,
    transforms.rejectImportExpressions,
    // Add custom transforms
    (source) => `"use strict";\n${source}`
  ],
  __options__: true
});

// Evaluate code with applied transforms
const result = secureCompartment.evaluate(`
  function calculate(x, y) {
    return x + y;
  }
  calculate(5, 3);
`);

Security Considerations

Transform Order Matters

Transforms are applied in the order specified. Security-critical transforms should typically come first:

// Correct order - security first
const transforms = [
  transforms.mandatoryTransforms,  // Security critical
  myCustomTransform               // Custom logic
];

// Incorrect order - custom transform might introduce vulnerabilities
const badTransforms = [
  myCustomTransform,              // Might add dangerous patterns
  transforms.mandatoryTransforms  // Too late to catch them
];

Evasion Transforms

The "evade" transforms are designed to work around the rejection transforms, but they may change code semantics:

// Original code
const code = 'const result = import("module");';

// Evade transform changes semantics
const evaded = transforms.evadeImportExpressionTest(code);
// Result: 'const result = __import__("module");'
// Note: __import__ is not the same as import()

Transform Performance

Transforms are applied synchronously and may impact performance for large codebases:

// For performance-critical applications, consider caching
const transformCache = new Map();

const cachedTransform = (source) => {
  if (transformCache.has(source)) {
    return transformCache.get(source);
  }
  
  const result = transforms.mandatoryTransforms(source);
  transformCache.set(source, result);
  return result;
};

Install with Tessl CLI

npx tessl i tessl/npm-ses

docs

assertions.md

compartments.md

environment-hardening.md

index.md

modules.md

tools.md

tile.json