Frontend Development 18 min read

JavaScript Sandboxes for Secure Micro‑Frontend Apps: Techniques & Examples

This article explains the concept of sandbox security mechanisms, explores their use cases in iPaaS API orchestration and micro‑frontend applications, compares eval, Function, with + proxy techniques, presents JavaScript, iframe and Node vm sandbox implementations, and details practical deployments within the Kraken framework and a centralized approval service.

Weimob Technology Center
Weimob Technology Center
Weimob Technology Center
JavaScript Sandboxes for Secure Micro‑Frontend Apps: Techniques & Examples

1. Introduction

Sandbox is a security mechanism that isolates program execution to protect the system. Developers frequently encounter sandbox environments such as Docker containers, CodeSandbox demos, and dynamic script execution.

2. Use Cases

Typical scenarios in the company include iPaaS visual API orchestration where custom Groovy scripts run in a sandbox, and micro‑frontend applications that need isolated global objects, routing, and state management.

3. JavaScript Sandbox Research

3.1 eval and Function

Both eval and the Function constructor can execute external code, but they expose global variables and cannot provide true isolation.

<code>// Bad code using eval
function looseJsonParse(obj){
    return eval(`(${obj})`);
}
console.log(looseJsonParse("{a:(4-1), b:function(){}, c:new Date()}"));

// Better code using Function
function looseJsonParse(obj){
    return Function(`"use strict";return (${obj})`)();
}
console.log(looseJsonParse("{a:(4-1), b:function(){}, c:new Date()}"));
</code>

3.2 with + Function + Proxy

3.2.1 with keyword

The with statement changes the scope chain, but it is prohibited in strict mode and is generally discouraged.

3.2.2 ES6 Proxy

Proxy can intercept property access, assignment, enumeration, and function calls.

<code>const handler = {
  get: function (obj, prop) {
    return prop in obj ? obj[prop] : 'weimob';
  },
};
const p = new Proxy({}, handler);
p.a = 2023;
p.b = undefined;
console.log(p.a, p.b); // 2023 undefined
console.log('c' in p, p.c); // false, weimob
</code>

3.2.3 Symbol.unscopables

If Symbol.unscopables is set to true, the with scope is ignored, allowing sandbox escape, so it must be handled explicitly.

3.2.4 Sandbox implementation

<code>function sandbox(code, context) {
  context = context || Object.create(null);
  const fn = new Function('context', `with(context){return (${code})}`);
  const proxy = new Proxy(context, {
    has(target, key) {
      if (["console", "setTimeout", "Date"].includes(key)) {
        return true;
      }
      if (!target.hasOwnProperty(key)) {
        throw new Error(`Illegal operation for key ${key}`);
      }
      return target[key];
    },
    get(target, key, receiver) {
      if (key === Symbol.unscopables) {
        return undefined;
      }
      return Reflect.get(target, key, receiver);
    }
  });
  return fn.call(proxy, proxy);
}
sandbox('3+2'); // 5
sandbox('console.log("微盟-智慧商业服务商")'); // Cannot read property 'log' of undefined
sandbox('console.log("微盟-智慧商业服务商")', {console: window.console}); // 微盟-智慧商业服务商
</code>

3.3 iframe based sandbox

Creating an iframe provides a native browser isolation layer; scripts run inside the iframe cannot affect the parent page.

<code>const parent = window;
const frame = document.createElement('iframe');
// Restrict iframe capabilities
frame.sandbox = 'allow-same-origin';
document.body.appendChild(frame);
const sandboxGlobal = frame.contentWindow;
</code>

3.4 Node runtime sandbox

3.4.1 Native vm module

The vm module creates a V8 context that can execute code with a given context object.

<code>const vm = require('node:vm');

const x = 1;

const context = { x: 2 };
vm.createContext(context); // Contextify the object.

const code = 'x += 40; var y = 17;';
vm.runInContext(code, context);

console.log(context.x); // 42
console.log(context.y); // 17

console.log(x); // 1; y is not defined.
</code>

Node's vm is not a security mechanism; untrusted code can escape via prototype chains.

node:vm module is not a security mechanism. Do not use it to run untrusted code.

3.4.2 Insecure reasons

Running code with vm.runInNewContext can access the global constructor and escape the sandbox.

<code>const vm = require('vm');
vm.runInNewContext('this.constructor.constructor("return process")().exit()');
</code>

3.4.3 Solution

Provide a clean context object without a prototype chain to prevent escape.

<code>const vm = require('vm');
let sandBox = Object.create(null);
sandBox.title = '微盟-智慧商业服务商';
sandBox.console = console;
vm.runInNewContext('console.log(title)', sandBox);
</code>

4. Practical Deployment

4.1 Kraken micro‑frontend framework

Kraken uses a sandbox based on a fake window and Proxy to give each micro‑frontend its own module, style, route, and state isolation, while supporting data sharing and event communication.

4.1.1 JS isolation

Create a sandbox instance and declare global APIs such as addEventListener, setTimeout, createElement, and intercept property access.

Use with to limit the scope of the execution context.

Parse dynamic JS with Function, intercept object access with Proxy, and bind this to the proxy.

4.1.2 CSS isolation

CSS isolation is achieved with CSS modules (hashed class names) and project‑level namespaces.

4.1.3 Data sharing & communication

Kraken exposes

kraken.data

for read/write data sharing and implements an event bus for parent‑child, sibling, and global communication.

4.2 Centralized approval service

The service enforces internal change management by requiring approval workflows for production changes. Business systems can integrate without custom code by configuring change points.

4.2.1 Node approval workflow

The gateway layer intercepts API calls, creates approval tickets, and allows scripts to extend ticket details.

4.2.2 Dynamic extension scripts

Business users can register a script that runs in a Node sandbox before ticket creation to enrich the details.

<code>/** 
 * Execute a user‑provided script string
 * @param {String} code JavaScript code
 * @param {Object} context Context visible to the code
 */
async function execScript(code, context) {
  try {
    const contextObject = Object.assign(context, {
      setTimeout,
      request
    });
    return vm.runInNewContext(code, contextObject);
  } catch (error) {
    return Promise.reject(error);
  }
}
</code>

Example user script:

<code>(() => ({ objectAction: `发布online:${packageName}@${packageVersion}` }))()
</code>

4.2.3 Summary

Although the vm module is not a security guarantee, the service runs inside a trusted internal network and adds manual review of scripts, providing sufficient safety for internal use.

5. Conclusion and Outlook

The article introduced sandbox concepts, application scenarios, and concrete JavaScript sandbox implementations for large‑scale front‑end platforms. Real‑world deployments show that sandbox strategies must be tailored to business needs, balancing flexibility and security.

javascriptproxynode.jsmicro-frontendsecuritySandboxiPaaS
Weimob Technology Center
Written by

Weimob Technology Center

Official platform of the Weimob Technology Center

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.