安全的模块化运行时

2020-08-26 13:24:43

作为一个稻草人,我想为JavaScript提出一个假设的运行时,并邀请人们仔细检查它是否解决了以下问题:这个运行时可以完全限制在与我们今天在Node.js、Deno和浏览器中运行的进程相同的进程中运行的第三方代码包的高级功能访问。该运行时可以支持来自现有JavaScript生态系统的入口,这对采用至关重要。

该建议基于安全运行时,因为这是从一开始就在中设计安全性的逻辑结论。JavaScript生态系统是由其运行时塑造的,只有通过提供安全的运行时目标,我们才能开始朝着更安全的属性塑造生态系统。运行时的形式是SES隔间模型的直接实现:全局对象应该没有功能(没有FETCH、Worker、Date Globals),只有内部函数,所有这些内部函数都作为安全的内部实例化提供。相反,所有功能都会导入。权限模型应该使用导入映射,并使用隔离作用域实现,其中作用域根本没有后备,除非在映射中明确定义,否则包不能导入其作用域之外的任何内容。这将导入映射视为由范围映射启用的解析和每包功能权限的单一真实来源。所有包之间的接口应该使用SafeObject、SafeFunction和SafeClass实现-这是模块系统本身确保包遵守的一个谨慎的通信语言子集。这可以是动态包装和展开,也可以是更静态的,甚至是用户定义的。现有的NPM生态系统应该通过能够在这个新的安全模型中运行至少90%的现有代码的代码解码器来支持。

Isolated Scopes提案是一个Import Maps扩展提案,允许导入地图全面定义哪些可以导入,哪些不可以导入。

该建议源于Node.js策略和导入映射最终趋同的想法。在SystemJS中,我们需要导入映射来支持完整性,而在Node.js中,我们需要策略来支持导入映射样式的作用域和映射。这里清晰的技术一致性完全是自然发生的,但是指向了一条路径:导入映射是定义功能完整性的天然主页。如果我们可以在这里结合目标,这就解决了事后考虑的安全性问题,因为构建导入映射的用户并不关心安全性,而是将其作为工作流本身的副作用(如果他们选择启用强大的功能实施)。其想法是,在功能模型中,您最终定义的权限类似于:除非通过功能系统显式授予访问权限,否则包不能导入包之外的任何内容。但是,此同一应用程序的导入映射类似于:{";Imports";:{";PackageA";:";/path/to/PackageA/main.js";},";Scope";:{";/path/to/PackageA/";:{";PackageB";:";/path/to/PackageB/main.js。/path/to/PackageB/";:{";fs";:";core:fs?local";}。

功能信息已经在导入映射中自然定义-也就是说,它是冗余信息。同样,另一方面,Node.js策略看起来很像一个导入映射。为支持这一点而对导入映射所做的更改非常小,并且可以作为扩展建议来完成:为导入映射提供一个新的隔离范围:true选项,该选项由顶级属性、标志或其他方式启用。将作用域限制为不允许导入该作用域之外的URL,除非在映射中明确定义了该URL。

通过这些小的调整,我们有可能将导入图转变为应用程序开发的主要模块化工作流,易于审核、阅读和管理,并且功能定义从一开始就是内置的。在包接口方面,导出的包绑定(例如Node.js";main";/";exports";field module exports)将使用安全接口系统。我们将现有包的面向外部的组件转换为此安全形式,例如:将转换为在运行时执行,如下所示:SafeFunction实现将确保调用者不会重新绑定此组件。因此,对软件创建者来说,所有的功能引用都是完全明确的。咨询仍然是必要的,但是在一个定义良好且受约束的权限模型中,该模型清楚地定义了升级的真正含义。SafeObject递归地应用,而SafeFunction又在运行时动态地将相同的清理应用于其返回值。实时导出绑定分配可以替换为SafeValue基类重新分配操作。基本体保持不变。应用这些安全功能的方式可能有多种: