我有一个CLI程序,可以使用描述指令的文件列表来执行,例如
node ./my-program.js ./instruction-1.js ./instruction-2.js ./instruction-3.js
这是我导入和验证目标文件是指令文件的方式:
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.
会触发,我会忽略该文件,但旁边动作将保留在后台。
如何安全验证目标文件签名?
最糟糕的情况是,如果文件被确定为不安全,是否存在完全沙箱化需求逻辑并终止进程的常规方法?
答案 0 :(得分:1)
最糟糕的情况是,如果文件被确定为不安全,是否存在完全沙箱化需求逻辑并终止进程的常规方法?
将检查逻辑移动到特定的js文件中。当一切都很好时,process.exit(0)
,如果错误,请process.exit(1)
。
在当前程序中,不是通过require加载文件,而是使用child_process.exec
来调用新文件,为其提供所需参数以了解要测试的文件。
在更新的程序中,绑定close事件以了解返回代码是0
还是1
。
如果您需要比0
或1
更多的信息,请在新的js文件中加载指令,将一些JSON.stringified数据打印到stdout
(console.log),然后在调用child_process.exec
的回调中检索JSON.parse。
或者,你看过AST处理吗? http://jointjs.com/demos/javascript-ast
它可以帮助您识别未嵌入导出函数的代码片段。
答案 1 :(得分:1)
(注意:我在IRC上与作者讨论了这个问题。我的答案中可能有一些背景不在原始问题中。)
鉴于您的方案纯粹是为了防止意外包含非指令文件,而不是防止恶意行为,使用Esprima之类的静态分析可能就足够了。 / p>
一种方法是要求每个指令文件导出某种具有name
属性的对象,该属性包含指令文件的名称。由于除了字符串文字之外没有任何东西要放在那里,你可以相当确定如果你不能通过静态分析找到name
属性,那么该文件不是指令文件 - 即使是像JavaScript这样的语言,也不是完全静态可分析的。
对于此线程的任何读者试图保护恶意演员,而不是意外 - 例如,当接受来自用户的不受信任的代码时:不能沙箱或仅使用Node.js'验证'JavaScript(也不使用vm
模块),上述解决方案对您不起作用。您将需要系统级容器化或虚拟化来安全地运行此类代码。没有其他选择。