如何静态分析一个文件适合导入?
我有CLI程序,可以用描述指令的文件列表执行,例如
node ./my-program.js ./instruction-1.js ./instruction-2.js ./instruction-3.js
这是我如何导入和validation目标文件是一个指令文件:
const requireInstruction = (instructionFilePath) => { const instruction = require(instructionFilePath) if (!instruction.getInstruction) { throw new Error('Not instruction file.'); } return instruction; };
这种方法的问题是,它会执行文件执行,无论它是否符合预期的签名,即如果文件包含一个副作用,如连接到数据库:
const mysql = require('mysql'); mysql.createConnection(..); module.exports = mysql;
Not instruction file.
会开火,我会忽略这个文件,但是这个副作用会保留在后台。
如何安全地validation目标文件签名?
最糟糕的情况是,有没有一个传统的方式来完全沙箱需求逻辑和杀死进程,如果文件被确定为不安全的?
最糟糕的情况是,有没有一个传统的方式来完全沙箱需求逻辑和杀死进程,如果文件被确定为不安全的?
将检查逻辑移入特定的js文件。 使它process.exit(0)
当一切正常, process.exit(1)
时,它是错的。
在你当前的程序中,不是通过require来加载文件,而是使用child_process.exec
来调用你的新文件,给它所需的参数来知道要testing哪个文件。
在更新的程序中,绑定closures事件以知道返回码是0
还是1
。
如果你需要比0
或1
更多的信息,进入新的js文件,它将加载指令,打印一些JSON.stringified数据到stdout
(console.log),然后检索JSON.parse它在调用callback到child_process.exec
。
或者,你看看AST处理? http://jointjs.com/demos/javascript-ast
它可以帮助您识别未embedded到导出函数中的代码段。
(注:我在IRC上与作者讨论过这个问题,在我的回答中可能有一些不在原始问题的背景。)
考虑到你的scheme纯粹是防止意外包含非指令文件,而不是防止恶意行为,使用类似Esprima的静态分析可能就足够了。
一种方法是要求每个指令文件都导出一些带有name
属性的对象,其中包含指令文件的名称。 除了string文字之外,没有什么东西可以放在里面,你可以相当肯定地说,如果你不能通过静态分析来定位一个name
属性,这个文件就不是一个指令文件 – 即使是像JavaScript这样的语言,完全可以静态分析。
对于这个线程的任何读者来说,都是为了防止恶意的行为者,而不是偶然的 – 例如,当接受来自用户的不可信的代码时:你不能单独使用Node.js来validationJavaScript(不是用vm
模块) ,而上述解决scheme不适合你 。 您将需要系统级容器化或虚拟化来安全地运行此类代码。 没有其他select。