Node环境下安全执行不可信字符串代码的可行方案探讨
Node环境安全执行不可信字符串代码的方案
场景说明
我用Node开发的应用,通过axios抓取HTML页面,经htmlparser2解析后将有效信息转为JSON格式返回给前端JS应用。页面中包含一段创建数组的JavaScript代码,我需要获取该数组的数据。目前有两种处理思路:
- 自行编写解析器提取所需信息(可行但实现复杂);
- 直接执行这段字符串形式的JS代码以获取数组值。
Node官方文档明确提示node:vm模块并非安全机制,不可用于运行不可信代码,而我获取的这段代码属于不可信范畴,因此想了解对应的安全执行方案。
附目标脚本片段:
hatizsakCucc = new Array(); hazbanCucc = new Array(); function adatokMessage(targyIndexStr,tomb) { var targyIndex = parseInt(targyIndexStr); if (tomb.length<1) alert("Nincs semmi!"); else alert(tomb[targyIndex]); } hatizsakCucc[0]="Név: ezüst\nSúly: 0.0001 kg.\nMennyiség: 453\nÖsszsúly: 0.0453 kg.\n"; hatizsakCucc[1]="Név: kaja\nSúly: 0.4 kg.\nÁr: 2 ezüst\nMennyiség: 68\nÖsszár: 136 ezüst\nÖsszsúly: 27.2 kg.\n"; hatizsakCucc[2]="Típus: fegyver\nNév: bot\nSúly: 2 kg.\nÁr: 6 ezüst\nMin. szint: 1\nMaximum sebzés: 6\nSebzés szórás: 5\nFajta: ütő/zúzó\n"; hatizsakCucc[3]="Típus: fegyver\nNév: parittya\nSúly: 0.3 kg.\nÁr: 14 ezüst\nMin. szint: 1\nMaximum sebzés: 7\nSebzés szórás: 4\nFajta: távolsági\n"; hatizsakCucc[4]="Név: csodatarisznya\nSúly: 4 kg.\nÁr: 1000 ezüst\nExtra: templomi árú\n"; hatizsakCucc[5]="Név: imamalom\nSúly: 5 kg.\nÁr: 150 ezüst\nExtra: templomi árú\n";
我已通过正则表达式hatizsakSzkript.match(/hatizsakCucc(.*)\\n/g);提取出hatizsakCucc数组的内容,后续会将数组元素解析为如下结构的对象:
{ nev: "ezüst", suly: 0.0001, mennyiseg: ... }
但仍好奇在Node环境中安全执行不可信字符串代码的可行方案。
安全执行方案
使用专业沙箱库
可以使用vm2这类基于Node vm模块增强的沙箱库,它提供了更严格的隔离机制,能限制代码对宿主环境敏感资源的访问,同时支持设置超时避免恶意代码阻塞进程。示例代码:
const { VM } = require('vm2'); const vm = new VM({ timeout: 1000, // 限制代码执行超时时间 allowAsync: false, // 禁止执行异步代码 sandbox: {} // 仅提供空沙箱环境,按需暴露必要全局对象 }); try { const targetArray = vm.run(` hatizsakCucc = new Array(); hatizsakCucc[0] = "Név: ezüst\\nSúly: 0.0001 kg.\\nMennyiség: 453\\nÖsszsúly: 0.0453 kg.\\n"; hatizsakCucc[1] = "Név: kaja\\nSúly: 0.4 kg.\\nÁr: 2 ezüst\\nMennyiség: 68\\nÖsszár: 136 ezüst\\nÖsszsúly: 27.2 kg.\\n"; hatizsakCucc; // 返回目标数组 `); console.log(targetArray); } catch (err) { console.error('代码执行出错:', err); }
严格管控原生vm模块的执行上下文
如果使用Node原生vm模块,必须手动严格限制执行上下文,仅暴露绝对必要的全局变量,同时禁用所有敏感API。示例:
const vm = require('vm'); // 仅提供必要的全局构造函数,避免暴露敏感对象 const context = { Array: Array }; try { const script = new vm.Script(` hatizsakCucc = new Array(); hatizsakCucc[0] = "Név: ezüst\\nSúly: 0.0001 kg.\\nMennyiség: 453\\nÖsszsúly: 0.0453 kg.\\n"; hatizsakCucc; `); // 在新上下文执行,设置超时防止死循环 const result = script.runInNewContext(context, { timeout: 1000 }); console.log(result); } catch (err) { console.error('执行错误:', err); }
注意:原生vm模块仍存在潜在的逃逸风险,仅适合对代码来源有一定信任度的场景,优先级低于专业沙箱库。
代码预处理+白名单校验
通过AST解析工具(如acorn)对目标代码片段进行语法分析,只允许白名单内的语法和操作(比如仅允许数组赋值、字符串字面量,禁止函数定义、循环、全局对象访问等)。这种方式安全性最高,但实现复杂度较大,适合已提取出目标代码片段的场景,可针对性地做语法校验。
内容的提问来源于stack exchange,提问作者digitaltos
相关产品推荐
相关产品推荐

