Hardened JavaScript for fearless cooperation through secure execution contexts and object-capability security
—
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.
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
});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
});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]);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)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' }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 5Creating 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