Skip to content
Web security Reviewed 2026-09-13

Unsafe runInContext

Scope and impact

Node.js vm.runInContext and related APIs execute JavaScript. A separate context is not a security boundary for untrusted code. Node's vm documentation explicitly warns against using it as a security mechanism. A timeout or an empty context does not turn it into a secure sandbox.

Replace code with data

Suppose a feature only needs to uppercase a short label. Accept that specific operation as data instead of accepting arbitrary JavaScript.

Unsafe: treat a submitted string as code.

import vm from 'node:vm';
function transform(requestText) {
  return vm.runInNewContext(requestText, {}, { timeout: 100 });
}

Safer: parse and validate the supported request format.

function transform(requestText) {
  if (typeof requestText !== 'string' || requestText.length > 4096) {
    throw new Error('Invalid request');
  }
  const value = JSON.parse(requestText);
  if (!value || Array.isArray(value) ||
      typeof value !== 'object' || value.operation !== 'uppercase' ||
      typeof value.text !== 'string' || value.text.length > 200) {
    throw new Error('Invalid operation');
  }
  return value.text.toUpperCase();
}

The result comes from a fixed application operation, not an evaluated expression. Bound the HTTP body before parsing too, and convert validation errors to appropriate client responses without exposing diagnostics. JSON.parse is a data parser; it does not provide business authorization or safe HTML output.

If arbitrary code execution is genuinely the product requirement, it needs a separately designed isolated execution service with minimal privileges, resource limits, controlled networking and lifecycle management. Replacing one vm method with another does not meet that requirement.

Regression check

Verify the accepted operation returns the expected label. Reject invalid JSON, oversized strings and unsupported operations. A text value such as 2 + 2 must remain text. See dynamic code execution and eval injection.