导读:本期聚焦于小伙伴创作的《在 Node.js 中,如何利用 vm 模块在沙箱环境中执行不可信代码?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《在 Node.js 中,如何利用 vm 模块在沙箱环境中执行不可信代码?》有用,将其分享出去将是对创作者最好的鼓励。

在 Node.js 中,vm 模块是官方提供的内置模块,能够在独立的上下文环境中执行 JavaScript 代码,通过隔离执行环境的方式,避免不可信代码直接访问宿主进程的全局对象和资源,是处理不可信代码执行场景的常用方案。

在 Node.js 中,如何利用 vm 模块在沙箱环境中执行不可信代码?

vm 模块核心 API 介绍

vm 模块提供了多个用于创建上下文和执行代码的方法,常用的核心 API 如下:

  • vm.createContext(contextObject):创建一个沙箱上下文对象,该对象会作为不可信代码执行时的全局对象,默认情况下不包含 Node.js 的全局 API。
  • vm.runInContext(code, contextifiedObject, options):在指定的沙箱上下文中执行代码,代码的全局作用域绑定到该上下文对象。
  • vm.runInNewContext(code, contextObject, options):创建新的上下文并执行代码,等价于先调用 createContext 再调用 runInContext。
  • vm.Script:用于预编译代码,可重复在多个上下文中执行,提升执行效率。

基础沙箱执行示例

以下是一个最简单的使用 vm 模块执行不可信代码的示例,仅提供基础的上下文环境:

const vm = require('vm');

// 定义沙箱上下文,仅包含允许不可信代码访问的变量
const sandbox = {
  a: 1,
  b: 2,
  console: console // 允许代码使用 console 输出,也可以按需限制
};

// 将普通对象转换为上下文对象
vm.createContext(sandbox);

// 要执行的不可信代码
const untrustedCode = `
  const sum = a + b;
  console.log('计算结果:', sum);
  sum;
`;

// 在沙箱中执行代码
const result = vm.runInContext(untrustedCode, sandbox);
console.log('执行返回值:', result);

构建安全的沙箱上下文

执行不可信代码时,需要严格控制沙箱上下文的内容,避免暴露敏感能力,以下是安全配置的核心要点:

1. 限制全局对象访问

不要在沙箱上下文中挂载 process、require、Buffer 等 Node.js 核心全局对象,否则不可信代码可能通过这些对象操作文件系统、发起网络请求或者退出进程。

2. 按需提供有限 API

如果不可信代码需要特定能力,仅提供最小权限的 API,例如仅允许计算时,不要提供任何 IO 相关的接口:

const vm = require('vm');

// 仅提供计算所需的变量,不挂载任何额外 API
const safeSandbox = {
  Math: Math, // 允许使用数学计算能力
  parseInt: parseInt // 允许类型转换
};

vm.createContext(safeSandbox);

const code = `
  const num = parseInt('123');
  const result = Math.pow(num, 2);
  result;
`;

const res = vm.runInContext(code, safeSandbox);
console.log('安全执行结果:', res);

3. 设置超时时间

不可信代码可能存在死循环,需要通过 options 设置超时时间,避免阻塞宿主进程:

const vm = require('vm');

const sandbox = {};
vm.createContext(sandbox);

const infiniteLoopCode = `
  while(true) {
    // 死循环代码
  }
`;

try {
  // 设置超时时间为 1000 毫秒,超时后抛出错误
  vm.runInContext(infiniteLoopCode, sandbox, { timeout: 1000 });
} catch (err) {
  console.log('执行超时:', err.message);
}

使用 vm.Script 预编译代码

如果需要多次执行同一段不可信代码,可以使用 vm.Script 预编译代码,提升执行效率:

const vm = require('vm');

// 预编译代码
const script = new vm.Script('a + b');

// 第一个上下文执行
const sandbox1 = { a: 10, b: 20 };
vm.createContext(sandbox1);
const res1 = script.runInContext(sandbox1);
console.log('第一次执行结果:', res1);

// 第二个上下文执行
const sandbox2 = { a: 30, b: 40 };
vm.createContext(sandbox2);
const res2 = script.runInContext(sandbox2);
console.log('第二次执行结果:', res2);

vm 模块的安全边界说明

需要注意 vm 模块并不是绝对安全的沙箱,存在以下限制:

  • 如果沙箱上下文包含了某些可以访问宿主环境的能力,例如挂载了可以操作原型链的方法,不可信代码可能通过原型链污染突破沙箱限制。
  • vm 模块无法完全隔离 V8 引擎层面的漏洞,因此不能用于执行完全不可信的恶意代码,仅适合处理低风险的第三方代码片段。
  • 不要将 vm 模块作为唯一的安全防护手段,对于高安全要求的场景,需要结合进程隔离、容器隔离等更严格的方案。
重要提醒:永远不要将 process、require 等敏感对象挂载到沙箱上下文中,也不要信任不可信代码的任何输入,所有传入沙箱的数据都需要先做校验。

完整安全执行示例

以下是一个完整的、相对安全的不可信代码执行示例,包含了上下文限制、超时设置、错误捕获:

const vm = require('vm');

/**
 * 安全执行不可信代码的方法
 * @param {string} code 不可信代码字符串
 * @param {object} customContext 自定义允许的上下文变量
 * @param {number} timeout 执行超时时间,单位毫秒
 * @returns {any} 代码执行返回值
 */
function safeRunUntrustedCode(code, customContext = {}, timeout = 1000) {
  // 构建基础沙箱,仅包含允许的 API
  const sandbox = {
    console: {
      log: (...args) => console.log('[沙箱输出]', ...args),
      error: (...args) => console.error('[沙箱错误]', ...args)
    },
    // 合并自定义上下文,自定义上下文会覆盖默认的同名属性
    ...customContext
  };

  // 转换为上下文对象
  vm.createContext(sandbox);

  try {
    // 执行代码,设置超时
    const result = vm.runInContext(code, sandbox, { timeout });
    return result;
  } catch (err) {
    console.error('代码执行失败:', err.message);
    return null;
  }
}

// 测试执行
const testCode = `
  const x = 5;
  const y = 3;
  const total = x * y;
  console.log('x * y 的结果是', total);
  total;
`;

const execResult = safeRunUntrustedCode(testCode, { x: 5 }, 500);
console.log('最终执行结果:', execResult);

Node.jsvm_modulesandboxuntrusted_code修改时间:2026-07-19 15:03:30

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。