Hardened JavaScript for fearless cooperation through secure execution contexts and object-capability security
npx @tessl/cli install tessl/npm-ses@1.14.0SES is a hardened JavaScript library that enables secure execution of third-party code through compartmentalization and object-capability security. It provides isolated execution contexts (compartments) with their own global objects while sharing frozen intrinsics to maintain compatibility, enforces strict mode for enhanced security, and implements the Principle of Least Authority (POLA) by providing compartments with no ambient authority by default.
npm install sesimport 'ses';
// This imports and installs all SES functionality globallyFor CommonJS:
require('ses');
// This imports and installs all SES functionality globallyIndividual shims can also be imported separately:
import 'ses/lockdown-shim.js'; // Just lockdown functionality
import 'ses/compartment-shim.js'; // Just Compartment constructor
import 'ses/assert-shim.js'; // Just assert functionality
import 'ses/console-shim.js'; // Just console enhancementsFor CommonJS:
require('ses/lockdown-shim.js'); // Just lockdown functionality
require('ses/compartment-shim.js'); // Just Compartment constructor
require('ses/assert-shim.js'); // Just assert functionality
require('ses/console-shim.js'); // Just console enhancementsFor tools and utilities:
import { transforms, scopeTerminators } from 'ses/tools.js';For CommonJS:
const { transforms, scopeTerminators } = require('ses/tools.js');import 'ses';
// Step 1: Harden the environment
lockdown();
// Step 2: Create isolated compartments for untrusted code
const compartment = new Compartment({
globals: {
console: harden(console),
// Only provide necessary capabilities
},
__options__: true, // temporary migration affordance
});
// Step 3: Safely execute code
const result = compartment.evaluate(`
// This code runs in isolation with limited capabilities
const data = { message: "Hello from compartment!" };
harden(data);
data;
`);
// Step 4: Use harden to make objects tamper-proof
const capability = harden({
getValue: () => "secure value",
increment: () => { counter++; }
});SES is built around several key security concepts:
harden() recursively freezes object graphs to prevent modificationCore functionality for hardening the JavaScript environment against prototype pollution and supply chain attacks.
function lockdown(options?: LockdownOptions): void;
function repairIntrinsics(options?: LockdownOptions): HardenIntrinsics;
function hardenIntrinsics(): Harden;
function harden<T>(value: T): T;Isolated execution contexts for running untrusted code with controlled capabilities and communication channels.
class Compartment {
constructor(options?: CompartmentOptions & { __options__: true });
evaluate(code: string, options?: EvaluateOptions): any;
import(specifier: string | null): Promise<{ namespace: ModuleExportsNamespace }>;
importNow(specifier: string): ModuleExportsNamespace;
load(specifier: string): Promise<void>;
module(specifier: string): ModuleExportsNamespace;
get globalThis(): Record<PropertyKey, any>;
get name(): string;
}Enhanced assertion library with detailed error reporting and causal console integration.
function assert(flag: any, details?: Details, errConstructor?: GenericErrorConstructor, options?: AssertMakeErrorOptions): asserts flag;
interface AssertionFunctions {
typeof: AssertTypeof;
equal<T>(actual: unknown, expected: T, details?: Details, errConstructor?: GenericErrorConstructor, options?: AssertMakeErrorOptions): asserts actual is T;
string(specimen: any, details?: Details): asserts specimen is string;
fail(details?: Details, errConstructor?: GenericErrorConstructor, options?: AssertMakeErrorOptions): never;
}Advanced module loading with hooks for custom resolution, transformation, and cross-compartment module sharing.
type ImportHook = (moduleSpecifier: string) => Promise<ModuleDescriptor>;
type ImportNowHook = (moduleSpecifier: string) => ModuleDescriptor | undefined;
type ResolveHook = (importSpecifier: string, referrerSpecifier: string) => string;
type ModuleMapHook = (moduleSpecifier: string) => ModuleDescriptor | undefined;Source transformation and scope manipulation utilities for advanced use cases.
interface TransformTools {
transforms: Record<string, Transform>;
}
interface ScopeTerminators {
strictScopeTerminator: any;
createSloppyGlobalsScopeTerminator: () => any;
}interface LockdownOptions {
regExpTaming?: 'safe' | 'unsafe';
localeTaming?: 'safe' | 'unsafe';
consoleTaming?: 'safe' | 'unsafe';
errorTrapping?: 'platform' | 'exit' | 'abort' | 'report' | 'none';
reporting?: 'platform' | 'console' | 'none';
unhandledRejectionTrapping?: 'report' | 'none';
errorTaming?: 'safe' | 'unsafe' | 'unsafe-debug';
evalTaming?: 'safe-eval' | 'unsafe-eval' | 'no-eval' | 'safeEval' | 'unsafeEval' | 'noEval';
stackFiltering?: 'concise' | 'omit-frames' | 'shorten-paths' | 'verbose';
overrideTaming?: 'moderate' | 'min' | 'severe';
overrideDebug?: Array<string>;
domainTaming?: 'safe' | 'unsafe';
legacyRegeneratorRuntimeTaming?: 'safe' | 'unsafe-ignore';
__hardenTaming__?: 'safe' | 'unsafe';
}
interface CompartmentOptions {
name?: string;
transforms?: Array<Transform>;
moduleMapHook?: ModuleMapHook;
importHook?: ImportHook;
importNowHook?: ImportNowHook;
importMetaHook?: ImportMetaHook;
resolveHook?: ResolveHook;
globals?: Map<string, any>;
modules?: Map<string, ModuleDescriptor>;
__shimTransforms__?: Array<Transform>;
__noNamespaceBox__?: boolean;
__native__?: boolean;
noAggregateLoadErrors?: boolean;
}
interface EvaluateOptions {
transforms?: Array<Transform>;
sloppyGlobalsMode?: boolean;
__moduleShimLexicals__?: Record<string, any>;
__evadeHtmlCommentTest__?: boolean;
__rejectSomeDirectEvalExpressions__?: boolean;
}type ModuleExportsNamespace = Record<string, any>;
type __LiveExportMap__ = Record<string, [string, boolean]>;
type __FixedExportMap__ = Record<string, [string]>;
type __ReexportMap__ = Record<string, Array<[string, string]>>;
interface PrecompiledModuleSource {
imports: Array<string>;
exports: Array<string>;
reexports: Array<string>;
__syncModuleProgram__: string;
__liveExportMap__: __LiveExportMap__;
__fixedExportMap__: __FixedExportMap__;
__reexportMap__: __ReexportMap__;
}
interface VirtualModuleSource {
imports: Array<string>;
exports: Array<string>;
execute(exportsTarget: Record<string, any>, compartment: Compartment, resolvedImports: Record<string, string>): void;
}
type ModuleSource = PrecompiledModuleSource | VirtualModuleSource;
type ModuleDescriptor = SourceModuleDescriptor | NamespaceModuleDescriptor | RecordModuleDescriptor | ModuleExportsNamespace | VirtualModuleSource | PrecompiledModuleSource | string;
interface SourceModuleDescriptor {
source: string | ModuleSource;
specifier?: string;
importMeta?: any;
compartment?: Compartment;
}
interface NamespaceModuleDescriptor {
namespace: string | ModuleExportsNamespace;
compartment?: Compartment;
}
interface RecordModuleDescriptor {
specifier: string;
record?: ModuleSource;
importMeta?: any;
compartment?: Compartment;
}type Transform = (source: string) => string;
type ResolveHook = (importSpecifier: string, referrerSpecifier: string) => string;
type ImportHook = (moduleSpecifier: string) => Promise<ModuleDescriptor>;
type ImportNowHook = (moduleSpecifier: string) => ModuleDescriptor | undefined;
type ModuleMapHook = (moduleSpecifier: string) => ModuleDescriptor | undefined;
type ImportMetaHook = (moduleSpecifier: string, importMeta: ImportMeta) => void;type Harden = <T>(value: T) => T;
type Details = string | DetailsToken;
type DetailsToken = Record<any, never>;
interface AssertMakeErrorOptions {
errorName?: string;
cause?: Error;
errors?: Error[];
sanitize?: boolean;
}
type GenericErrorConstructor = ErrorConstructor | AggregateErrorConstructor;
type Raise = (reason: Error) => void;
type MakeAssert = (raise?: Raise, unredacted?: boolean) => Assert;
interface StringablePayload {
toString(): string;
}