You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何防止exec执行写入操作?多语言在线编译器Node代码执行安全问题

如何避免Node.js在线编译器中exec()修改系统文件

嘿,我刚好折腾过类似的在线编译器安全问题,针对你提到的exec()执行用户代码带来的系统文件风险,结合你已经尝试过vm和vm2的情况,给你几个落地性强的解决方案:

1. 彻底放弃直接用exec(),用vm2构建严格沙箱

你之前试的vm和vm2是对的,但如果还是用exec()去跑用户代码文件,等于完全绕开了沙箱的隔离——因为exec()是直接启动一个完整的Node进程,拥有宿主系统的权限。正确的做法是把用户代码直接放到vm2的沙箱里执行,而不是写入文件再用exec调用。

举个实用的vm2配置示例:

const { NodeVM } = require('vm2');

// 构建一个几乎完全隔离的沙箱
const vm = new NodeVM({
  require: {
    external: false, // 禁止加载任何第三方npm包
    builtin: [], // 禁用所有Node内置模块(fs、child_process全封死)
    root: './sandbox', // 哪怕开了模块加载,也限制在指定目录
  },
  sandbox: {}, // 自定义沙箱的全局对象,不暴露Node原生的global
  timeout: 5000, // 限制代码最多跑5秒,防死循环
  memoryLimit: 128 * 1024 * 1024, // 限制内存使用,防内存溢出
});

// 直接执行用户输入的代码
try {
  const executionResult = vm.run(userSubmittedCode);
  // 返回结果给用户
} catch (error) {
  // 捕获并返回错误信息
}

这样用户代码完全在沙箱里跑,根本碰不到fs这类危险模块,自然没法修改系统文件。

2. 若必须用exec(),则做权限隔离+容器化

如果因为某些特殊需求(比如需要完整的Node环境支持)必须用exec()启动Node进程,那一定要做多层权限隔离:

  • 创建一个低权限系统用户(比如sandbox-runner),这个用户只拥有临时目录的读写权限,对系统核心目录(/etc、/usr等)只有只读权限,完全没有修改/删除权限。
  • 把用户代码写入到/tmp下的唯一临时目录(用crypto.randomUUID()生成唯一目录名,避免冲突),然后切换到低权限用户执行node ./temp-code.js。
  • 更彻底的方式是用Docker容器:把用户代码放到隔离的容器中执行,容器挂载宿主的临时目录(只读或仅写入临时文件),系统目录全部设为只读。就算用户代码搞破坏,也只影响容器内部,不会波及宿主系统。

3. 代码预处理:提前过滤危险API

在把用户代码送入沙箱或执行之前,先做静态代码扫描,过滤掉危险代码:

  • 用@babel/parser解析用户代码的AST,检测是否有require('fs')、process、child_process.spawn这类危险调用,一旦发现直接拒绝执行。
  • 也可以用简单的字符串匹配(虽然AST更可靠),比如检查代码中是否包含fs.unlink、rm -rf这类关键词。

4. 临时文件的安全规范

如果还是需要写入临时文件,一定要遵守这些规则:

  • 用os.tmpdir()创建临时文件,并且生成唯一的文件名(比如temp-${crypto.randomUUID()}.js),避免恶意覆盖其他文件。
  • 设置临时文件的权限为600,只有当前用户能读写,防止其他进程篡改。
  • 代码执行完成后立即删除临时文件,避免残留。

最后提醒一句:安全防护永远是多层的,不要只依赖单一方案。就算用了vm2,也要定期更新库版本,因为安全漏洞可能会被发现。另外,永远不要信任用户输入的任何代码,多重防护才是稳妥的。

内容的提问来源于stack exchange,提问作者Gurleen Sethi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:10:16