npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@stevenleep/sandbox

v1.0.1

Published

A powerful JavaScript sandbox library that provides multiple sandbox implementation options for safely executing untrusted code in browser environments.

Downloads

11

Readme

@stevenleep/sandbox

A powerful JavaScript sandbox library that provides multiple sandbox implementation options for safely executing untrusted code in browser environments. Perfect for micro-frontends and applications that need to run third-party code securely.

Features

  • Multiple sandbox implementations:

    • ProxySandbox: Based on Proxy to intercept global object operations
    • WithEvalSandbox: Based on with+eval to execute code, isolating global variables
    • ShadowRealmSandbox: Based on the new ShadowRealm API (with polyfill and fallback options)
    • SnapshotSandbox: Based on snapshots to save and restore global state
  • Enhanced Security:

    • Complete isolation from global objects
    • Strict mode execution by default
    • Prevention of prototype pollution attacks
    • Code validation to detect potentially dangerous patterns
    • Blacklisting of sensitive APIs
    • Control over network access
  • Resource Management:

    • Execution timeouts to prevent infinite loops
    • Memory usage monitoring
    • Performance measurement
    • Automatic cleanup of resources
  • Advanced Features:

    • Support for asynchronous code execution (async/await)
    • ES module loading support
    • Event listener management to prevent memory leaks
    • Enhanced error handling with detailed information
    • Symbol handling, including Symbol.unscopables
    • Tiered implementation approach with graceful fallback

Installation

npm install @stevenleep/sandbox

Basic Usage

import { createSandbox, SandboxType, getBestSandboxType } from '@stevenleep/sandbox';

// Auto-detect best sandbox implementation for current environment
const bestSandboxType = getBestSandboxType();
const sandbox = createSandbox(bestSandboxType, {
  name: 'my-sandbox'
});

// Or explicitly select a sandbox type
const proxySandbox = createSandbox(SandboxType.Proxy, {
  name: 'proxy-sandbox',
  strictMode: true
});

// Activate the sandbox
sandbox.activate();

// Execute code in the sandbox
const result = sandbox.execScript(`
  const message = 'Hello from sandbox!';
  console.log(message);
  
  // Won't affect the global environment
  window.foo = 'bar';
  
  // Return value
  message;
`);

console.log(result); // "Hello from sandbox!"
console.log(window.foo); // undefined - the property is contained within the sandbox

// When finished
sandbox.deactivate();
sandbox.destroy(); // Clean up any resources

ShadowRealm Implementation

The ShadowRealmSandbox provides the most secure isolation and uses a tiered implementation approach:

  1. Native ShadowRealm API (if available in the browser)
  2. ShadowRealm polyfill (automatically used if native implementation is not available)
  3. Iframe-based fallback (as last resort if polyfill fails)
import { ShadowRealmSandbox, isShadowRealmSupported } from '@stevenleep/sandbox';

// Check if ShadowRealm is supported (either native or via polyfill)
console.log(`ShadowRealm is ${isShadowRealmSupported() ? 'supported' : 'not supported'}`);

// Create a ShadowRealm sandbox
const sandbox = new ShadowRealmSandbox({
  name: 'shadowrealm-sandbox',
  initScript: 'console.log("Sandbox initialized")'
});

// The implementation will automatically choose the best available option:
// - Native ShadowRealm if supported by the browser
// - ShadowRealm polyfill if native is not available
// - Iframe fallback as last resort

// Execute code - this works the same regardless of which implementation is used
sandbox.execScript(`
  // This code runs in complete isolation
  const privateData = { secret: 'safe' };
  
  // Only explicitly exported values are accessible outside
  globalThis.exposedValue = 'exposed';
`);

// Access exported values
const value = await sandbox.execScriptAsync(`globalThis.exposedValue`);
console.log(value); // "exposed"

// Load an ES module
const module = await sandbox.loadModule('https://example.com/module.js');

Proxy Sandbox

The ProxySandbox provides a good balance of performance and complete isolation:

import { ProxySandbox } from '@stevenleep/sandbox';

const sandbox = new ProxySandbox({
  name: 'proxy-sandbox',
  strictMode: true, // IMPORTANT: Always set to true for proper isolation
  blacklist: ['localStorage', 'sessionStorage'],
  whitelist: ['console', 'setTimeout']
});

sandbox.activate();

// Variables defined in the sandbox stay in the sandbox
sandbox.execScript(`
  // This will be contained within the sandbox
  window.testValue = 'sandbox value';
  
  // This logs the sandboxed value
  console.log(window.testValue); // 'sandbox value'
  
  // This will log a warning and not be modified due to blacklist
  localStorage.setItem('test', 'value');
`);

// Variables defined in the sandbox are NOT accessible from outside
console.log(window.testValue); // undefined - completely isolated

sandbox.destroy();

WithEval Sandbox

The WithEvalSandbox provides simple global variable isolation:

import { WithEvalSandbox } from '@stevenleep/sandbox';

const sandbox = new WithEvalSandbox({
  name: 'eval-sandbox',
  globals: {
    // Custom globals to inject
    customAPI: {
      getData: () => 'Custom data'
    }
  }
});

sandbox.activate();

const result = sandbox.execScript(`
  // Access custom global
  const data = customAPI.getData();
  
  // Return the data
  data;
`);

console.log(result); // "Custom data"

sandbox.destroy();

ShadowRealm Sandbox

The ShadowRealmSandbox uses the new ShadowRealm API (with polyfill and iframe fallback) to provide complete isolation:

import { ShadowRealmSandbox } from '@stevenleep/sandbox';

const sandbox = new ShadowRealmSandbox({
  name: 'shadowrealm-sandbox',
  // Force using iframe fallback for compatibility
  forceIframe: true,
  // Set execution timeout
  timeLimit: 1000,
  // Security configuration
  security: {
    preventSensitiveAPIs: true,
    allowNetwork: false
  },
  // Module options if needed
  moduleOptions: {
    baseURL: 'https://example.com/',
    trustedSources: ['https://trusted-cdn.com/']
  }
});

sandbox.activate();

// Execute code in complete isolation
sandbox.execScript(`
  // Code runs in completely separate environment
  const secretData = 'This is isolated';
  
  // Define a function we'll export
  function calculateResult(input) {
    return input * 2;
  }
`);

// Export a function from main environment to sandbox
sandbox.exportFunction('multiplyByThree', (value) => value * 3);

// Use the exported function in sandbox
const result = sandbox.execScript(`
  // Use the function exported from main environment
  const result = multiplyByThree(10);
  return result;
`);
console.log(result); // 30

// Import a function from sandbox
const calculate = sandbox.importFunction('calculateResult');
console.log(calculate(5)); // 10

// Async execution with timeout
const asyncResult = await sandbox.execScriptAsync(`
  return new Promise(resolve => {
    setTimeout(() => resolve('Completed'), 100);
  });
`, 500);

sandbox.destroy();

Snapshot Sandbox

The SnapshotSandbox captures and restores window state:

import { SnapshotSandbox } from '@stevenleep/sandbox';

const sandbox = new SnapshotSandbox({
  name: 'snapshot-sandbox'
});

// Save current window state
sandbox.activate();

// Run code that modifies window
sandbox.execScript(`
  window.modifiedValue = 'modified';
`);

console.log(window.modifiedValue); // "modified"

// Restore original window state
sandbox.deactivate();

console.log(window.modifiedValue); // undefined - window restored

Security Considerations

  • ShadowRealmSandbox: Provides the strongest isolation

    • Native implementation offers true realm-based isolation
    • Polyfill provides excellent compatibility across browsers
    • Even the iframe fallback gives strong isolation guarantees
    • Best choice for executing untrusted code
  • ProxySandbox: Offers a good balance between isolation and compatibility

    • IMPORTANT: Always set strictMode: true for complete isolation
    • With proper configuration, provides complete isolation of window modifications
    • Sandbox variables remain in the sandbox and do not leak to global scope
    • Uses an isolated object model separate from the global window
    • Good choice for semi-trusted code when ShadowRealm is not available
  • WithEvalSandbox: Provides limited isolation

    • Mainly isolates global variables, not full security boundary
    • Good for code organization more than security
    • Not recommended for untrusted code
  • SnapshotSandbox: Focuses on state restoration rather than isolation

    • Useful for temporarily modifying window state
    • Not a security boundary for untrusted code
    • Good for isolation between trusted components
  • General Security Tips:

    • Always sanitize inputs before passing to any sandbox
    • Validate outputs returned from sandbox execution
    • Apply Content Security Policy (CSP) restrictions
    • Consider using a web worker for additional isolation
    • Limit execution time with timeouts
    • Restrict access to sensitive APIs through blacklists

Ensuring Complete Isolation

For maximum security, use the following patterns:

import { createSandbox, getBestSandboxType } from '@stevenleep/sandbox';

// Always use the best available sandbox type with strictMode enabled
const sandbox = createSandbox(getBestSandboxType(), {
  name: 'secure-sandbox',
  strictMode: true,  // Critical for isolation
  blacklist: [
    // Restrict access to sensitive APIs
    'localStorage', 'sessionStorage', 'indexedDB', 
    'WebSocket', 'XMLHttpRequest', 'fetch',
    // Prevent DOM access
    'document', 'navigator', 'location'
  ]
});

sandbox.activate();

// Variables defined inside stay inside
sandbox.execScript(`
  window.secretData = "This stays in the sandbox";
`);

// Global window is completely unmodified
console.log(window.secretData); // undefined

sandbox.destroy();

Advanced Usage

Performance Measurement

import { performanceMeasure } from '@stevenleep/sandbox';

const { start, end, measure } = performanceMeasure('code-execution');

start();
// Code to measure
const result = heavyComputation();
const duration = end();

console.log(`Execution took ${duration}ms`);

Error Handling

import { wrapExecution, formatError } from '@stevenleep/sandbox';

const result = wrapExecution(() => {
  // Potentially dangerous code
  return riskyOperation();
});

if (result.error) {
  console.error('Error occurred:', formatError(result.error));
} else {
  console.log('Success:', result.value);
}

License

MIT