SES: Hardened JavaScript for Secure Execution

2.0.0 · active · verified Sun Apr 19

SES (Secure EcmaScript) is a JavaScript shim providing a hardened environment for robust security and fearless cooperation. It implements Hardened JavaScript, a subset of JavaScript proposed to ECMA TC39, designed to prevent prototype pollution and other common vulnerabilities. The current stable version, 2.0.0, focuses on plugging side-channel attacks and refining security guarantees. SES operates by 'locking down' the global environment, freezing intrinsic objects, and providing the `Compartment` constructor for creating isolated execution contexts. Each `Compartment` has its own global object and module system but shares hardened, immutable primordials with other compartments. This approach ensures that mutually suspicious code can interact safely via object-capability (ocap) principles, where powers are explicitly granted. The package maintains an active release cadence, with frequent updates across the broader `@endo` ecosystem. Key differentiators include its comprehensive protection against tampering with built-in objects, enforcement of strict mode, and its utility in sandboxing third-party code for applications like blockchain smart contracts and browser extensions, notably used by Agoric and MetaMask.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates locking down the global environment and securely executing untrusted TypeScript code within an isolated Compartment, explicitly granting limited capabilities like logging and a custom greeting function. It also shows how attempts at prototype pollution or unauthorized global access are prevented.

import { lockdown, Compartment, harden } from 'ses';

// Step 1: Lock down the global environment to prevent tampering.
// This should be done as early as possible in your application's lifecycle.
lockdown();

console.log('Global environment locked down.');

// Step 2: Create a new Compartment for secure execution of untrusted code.
// Compartments are isolated and by default have no ambient authority (e.g., no `fetch`).
const untrustedCompartment = new Compartment({
  globals: {
    // Grant specific global capabilities to the compartment.
    log: harden(console.log),
    greet: harden((name: string) => `Hello, ${name} from compartment!\n`),
  },
});

// Step 3: Evaluate untrusted code within the compartment.
// The code only has access to its explicit globals and hardened intrinsics.
const untrustedCode = `
  try {
    log(greet('World'));
    // Attempting to access unauthorized globals will fail.
    // console.error('This should not be accessible.');
    // new Function('return this')().alert('Attempted to access window!');
    log('Attempting to modify Object.prototype...');
    Object.prototype.evil = 'muahaha'; // This will fail due to lockdown
  } catch (e: any) {
    log('Caught expected error: ' + e.message);
  }
  const func = new Function('return 1 + 1;'); // This will throw after lockdown
`;

try {
  untrustedCompartment.evaluate(untrustedCode);
} catch (e: any) {
  console.error('Error evaluating untrusted code:', e.message);
}

// Verify global prototype pollution did not occur in the main realm
if (Object.prototype.hasOwnProperty('evil')) {
  console.error('Prototype pollution detected in main realm!');
} else {
  console.log('Main realm is still secure.');
}

view raw JSON →