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

modules.mddocs/

Module System

Advanced module loading system with hooks for custom resolution, transformation, and cross-compartment module sharing. The SES module system enables secure module loading with fine-grained control over how modules are resolved, loaded, and shared between compartments.

Capabilities

Module Loading Hooks

Hook functions that customize how modules are resolved and loaded within compartments.

/**
 * Resolves import specifiers to full module specifiers
 * @param importSpecifier - The specifier used in import statement
 * @param referrerSpecifier - The specifier of the importing module
 * @returns Full module specifier for loading
 */
type ResolveHook = (importSpecifier: string, referrerSpecifier: string) => string;

/**
 * Asynchronously loads modules by specifier
 * @param moduleSpecifier - Full module specifier to load
 * @returns Promise resolving to module descriptor
 */
type ImportHook = (moduleSpecifier: string) => Promise<ModuleDescriptor>;

/**
 * Synchronously loads modules by specifier
 * @param moduleSpecifier - Full module specifier to load
 * @returns Module descriptor or undefined if not found
 */
type ImportNowHook = (moduleSpecifier: string) => ModuleDescriptor | undefined;

/**
 * Dynamically maps module specifiers to descriptors
 * @param moduleSpecifier - Module specifier to lookup
 * @returns Module descriptor or undefined if not found
 */
type ModuleMapHook = (moduleSpecifier: string) => ModuleDescriptor | undefined;

/**
 * Customizes import.meta objects for modules
 * @param moduleSpecifier - The module's specifier
 * @param importMeta - The import.meta object to customize
 */
type ImportMetaHook = (moduleSpecifier: string, importMeta: ImportMeta) => void;

Usage Examples:

import 'ses';

lockdown();

// Custom module resolution
const resolveHook = (importSpecifier, referrerSpecifier) => {
  if (importSpecifier.startsWith('./')) {
    // Resolve relative imports
    const referrerPath = referrerSpecifier.split('/').slice(0, -1);
    return [...referrerPath, importSpecifier.slice(2)].join('/');
  }
  if (importSpecifier.startsWith('virtual:')) {
    // Handle virtual modules
    return importSpecifier;
  }
  // Default resolution
  return importSpecifier;
};

// Async module loading
const importHook = async (moduleSpecifier) => {
  if (moduleSpecifier.startsWith('virtual:math')) {
    return {
      source: `
        export const add = (a, b) => a + b;
        export const multiply = (a, b) => a * b;
        export const PI = 3.14159;
      `
    };
  }
  if (moduleSpecifier.startsWith('http://')) {
    const response = await fetch(moduleSpecifier);
    const source = await response.text();
    return { source };
  }
  throw new Error(`Cannot load module: ${moduleSpecifier}`);
};

// Sync module loading
const importNowHook = (moduleSpecifier) => {
  if (moduleSpecifier === 'builtin:console') {
    return {
      namespace: { log: console.log, error: console.error }
    };
  }
  // Return undefined for modules that can't be loaded synchronously
};

// Dynamic module mapping
const moduleMapHook = (moduleSpecifier) => {
  const moduleRegistry = {
    'app/config': {
      namespace: { apiUrl: 'https://api.example.com', debug: true }
    },
    'app/utils': {
      source: './utils/index.js',
      compartment: utilsCompartment
    }
  };
  return moduleRegistry[moduleSpecifier];
};

// Create compartment with hooks
const compartment = new Compartment({
  resolveHook,
  importHook,
  importNowHook,
  moduleMapHook,
  __options__: true
});

Module Descriptors

Various descriptor formats for specifying how modules should be loaded and initialized.

/**
 * Descriptor using source code or compiled module
 */
interface SourceModuleDescriptor {
  /** Module source code or compiled module source */
  source: string | ModuleSource;
  /** Optional specifier for the module */
  specifier?: string;
  /** Optional import.meta properties */
  importMeta?: any;
  /** Optional compartment to load/initialize in */
  compartment?: Compartment;
}

/**
 * Descriptor using pre-existing namespace
 */
interface NamespaceModuleDescriptor {
  /** Namespace object or specifier in another compartment */
  namespace: string | ModuleExportsNamespace;
  /** Optional compartment containing the namespace */
  compartment?: Compartment;
}

/**
 * Legacy descriptor format (being deprecated)
 */
interface RecordModuleDescriptor {
  /** Module specifier */
  specifier: string;
  /** Optional compiled module record */
  record?: ModuleSource;
  /** Optional import.meta properties */
  importMeta?: any;
  /** Compartment to use (defaults to self) */
  compartment?: Compartment;
}

/**
 * Union type of all module descriptor formats
 */
type ModuleDescriptor = 
  | SourceModuleDescriptor 
  | NamespaceModuleDescriptor 
  | RecordModuleDescriptor 
  | ModuleExportsNamespace 
  | VirtualModuleSource 
  | PrecompiledModuleSource 
  | string;

Usage Examples:

import 'ses';

lockdown();

const compartment = new Compartment({
  modules: {
    // Source descriptor with string source
    'math/basic': {
      source: `
        export const add = (a, b) => a + b;
        export const subtract = (a, b) => a - b;
      `
    },
    
    // Namespace descriptor with direct object
    'config/app': {
      namespace: {
        apiEndpoint: 'https://api.example.com',
        version: '1.0.0'
      }
    },
    
    // Cross-compartment namespace reference
    'utils/shared': {
      namespace: 'utils/index',
      compartment: sharedUtilsCompartment
    },
    
    // With custom import.meta
    'app/main': {
      source: `
        console.log('Module URL:', import.meta.url);
        export const init = () => 'initialized';
      `,
      importMeta: {
        url: 'file:///app/main.js',
        env: 'production'
      }
    }
  },
  __options__: true
});

Module Source Types

Different types of module source representations for advanced use cases.

/**
 * Pre-compiled module source with analysis metadata
 */
interface PrecompiledModuleSource {
  /** Array of import specifiers */
  imports: Array<string>;
  /** Array of export names */
  exports: Array<string>;
  /** Array of re-export specifiers */
  reexports: Array<string>;
  /** Compiled module program as string */
  __syncModuleProgram__: string;
  /** Map of live (mutable) export bindings */
  __liveExportMap__: __LiveExportMap__;
  /** Map of fixed (immutable) export bindings */
  __fixedExportMap__: __FixedExportMap__;
  /** Map of re-export bindings */
  __reexportMap__: __ReexportMap__;
}

/**
 * Virtual module source with custom execution logic
 */
interface VirtualModuleSource {
  /** Array of import specifiers this module needs */
  imports: Array<string>;
  /** Array of names this module exports */
  exports: Array<string>;
  
  /**
   * Custom execution function for the module
   * @param exportsTarget - Object to populate with exports
   * @param compartment - The compartment executing the module
   * @param resolvedImports - Map of import names to resolved specifiers
   */
  execute(
    exportsTarget: Record<string, any>,
    compartment: Compartment,
    resolvedImports: Record<string, string>
  ): void;
}

/** Union type of module source formats */
type ModuleSource = PrecompiledModuleSource | VirtualModuleSource;

Usage Examples:

import 'ses';

lockdown();

// Virtual module source example
const createDatabaseModule = (connectionString) => ({
  imports: [],
  exports: ['connect', 'query', 'disconnect'],
  execute(exportsTarget, compartment, resolvedImports) {
    let connection = null;
    
    exportsTarget.connect = async () => {
      connection = await createConnection(connectionString);
      return connection;
    };
    
    exportsTarget.query = async (sql, params) => {
      if (!connection) throw new Error('Not connected');
      return await connection.query(sql, params);
    };
    
    exportsTarget.disconnect = async () => {
      if (connection) {
        await connection.close();
        connection = null;
      }
    };
  }
});

// Use virtual module
const compartment = new Compartment({
  modules: {
    'db/connection': createDatabaseModule('postgresql://localhost/mydb')
  },
  __options__: true
});

const db = compartment.importNow('db/connection');
await db.connect();
const results = await db.query('SELECT * FROM users WHERE active = ?', [true]);

Advanced Module Patterns

Module Federation

Sharing modules across multiple compartments:

import 'ses';

lockdown();

// Shared library compartment
const libraryCompartment = new Compartment({
  modules: {
    'lodash': {
      source: `
        export const map = (array, fn) => array.map(fn);
        export const filter = (array, fn) => array.filter(fn);
        export const reduce = (array, fn, initial) => array.reduce(fn, initial);
      `
    },
    'validator': {
      source: `
        export const isEmail = (str) => /\\S+@\\S+\\.\\S+/.test(str);
        export const isURL = (str) => /^https?:\\/\\//.test(str);
      `
    }
  },
  __options__: true
});

// Application compartments that use shared libraries
const createAppCompartment = (name) => new Compartment({
  name,
  modules: {
    // Reference modules from library compartment
    'lodash': {
      namespace: 'lodash',
      compartment: libraryCompartment
    },
    'validator': {
      namespace: 'validator', 
      compartment: libraryCompartment
    }
  },
  __options__: true
});

const userAppCompartment = createAppCompartment('user-app');
const adminAppCompartment = createAppCompartment('admin-app');

// Both apps can use the same shared modules
const userLodash = userAppCompartment.importNow('lodash');
const adminValidator = adminAppCompartment.importNow('validator');
console.log(userLodash === adminValidator); // false (different namespaces)

Dynamic Module Loading

Loading modules based on runtime conditions:

import 'ses';

lockdown();

const createPluginSystem = () => {
  const plugins = new Map();
  
  return new Compartment({
    moduleMapHook: (specifier) => {
      if (specifier.startsWith('plugin:')) {
        const pluginName = specifier.slice(7);
        return plugins.get(pluginName);
      }
    },
    
    importHook: async (specifier) => {
      if (specifier.startsWith('dynamic:')) {
        const moduleName = specifier.slice(8);
        
        // Load module based on environment
        if (process.env.NODE_ENV === 'development') {
          return {
            source: `export default { name: '${moduleName}', env: 'dev' };`
          };
        } else {
          return {
            source: `export default { name: '${moduleName}', env: 'prod' };`
          };
        }
      }
      
      throw new Error(`Unknown module: ${specifier}`);
    },
    
    globals: {
      registerPlugin: harden((name, descriptor) => {
        plugins.set(name, descriptor);
      }),
      console: harden(console)
    },
    
    __options__: true
  });
};

const pluginSystem = createPluginSystem();

// Register a plugin
pluginSystem.globalThis.registerPlugin('auth', {
  source: `
    export const authenticate = (token) => token === 'valid';
    export const authorize = (user, resource) => user.role === 'admin';
  `
});

// Use the plugin
const auth = pluginSystem.importNow('plugin:auth');
console.log(auth.authenticate('valid')); // true

// Load dynamic module
const dynModule = await pluginSystem.import('dynamic:feature-a');
console.log(dynModule.default); // { name: 'feature-a', env: 'dev' or 'prod' }

Module Transformation Pipeline

Transforming modules during loading:

import 'ses';

lockdown();

const createTransformingCompartment = () => {
  const transforms = [
    // Add logging to all functions
    (source) => {
      return source.replace(
        /export\s+(?:const|function)\s+(\w+)/g,
        (match, name) => {
          return match + `\nconsole.log('Calling ${name}');`;
        }
      );
    },
    
    // Replace development assertions
    (source) => {
      if (process.env.NODE_ENV === 'production') {
        return source.replace(/assert\([^)]+\);?/g, '');
      }
      return source;
    }
  ];
  
  return new Compartment({
    importHook: async (specifier) => {
      let source = await fetchModuleSource(specifier);
      
      // Apply transformations
      for (const transform of transforms) {
        source = transform(source);
      }
      
      return { source };
    },
    
    globals: { console: harden(console) },
    __options__: true
  });
};

const fetchModuleSource = async (specifier) => {
  // Mock module source
  if (specifier === 'math-utils') {
    return `
      export const add = (a, b) => {
        assert(typeof a === 'number');
        assert(typeof b === 'number');
        return a + b;
      };
      
      export const multiply = (a, b) => {
        assert(typeof a === 'number');
        assert(typeof b === 'number');
        return a * b;
      };
    `;
  }
  throw new Error(`Module not found: ${specifier}`);
};

const compartment = createTransformingCompartment();
const mathUtils = await compartment.import('math-utils');
console.log(mathUtils.namespace.add(2, 3)); // Logs: "Calling add" then returns 5

Module Sandboxing

Creating isolated environments for different types of modules:

import 'ses';

lockdown();

const createSandboxedModule = (source, permissions = {}) => {
  const sandbox = new Compartment({
    globals: {
      // Only provide explicitly allowed capabilities
      ...(permissions.console && { console: harden(console) }),
      ...(permissions.setTimeout && { setTimeout: harden(setTimeout) }),
      ...(permissions.fetch && { fetch: harden(fetch) }),
      
      // Custom API surface
      ...(permissions.storage && {
        storage: harden({
          get: (key) => localStorage.getItem(`sandbox:${key}`),
          set: (key, value) => localStorage.setItem(`sandbox:${key}`, value)
        })
      })
    },
    __options__: true
  });
  
  return sandbox.evaluate(`
    ${source}
    // Return the module's exports
    (typeof exports !== 'undefined' ? exports : 
     typeof module !== 'undefined' && module.exports ? module.exports :
     {})
  `);
};

// Load user-provided plugin with minimal permissions
const userPlugin = createSandboxedModule(`
  exports.processData = (data) => {
    console.log('Processing:', data);
    return data.map(x => x * 2);
  };
`, {
  console: true // Only allow console access
});

// Load trusted module with more permissions
const trustedModule = createSandboxedModule(`
  exports.saveData = async (data) => {
    storage.set('lastData', JSON.stringify(data));
    const response = await fetch('/api/save', {
      method: 'POST',
      body: JSON.stringify(data)
    });
    return response.json();
  };
`, {
  console: true,
  storage: true,
  fetch: true
});

// Use the sandboxed modules
const processedData = userPlugin.processData([1, 2, 3]); // [2, 4, 6]
await trustedModule.saveData(processedData);

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