运行时修改ECMAScript模块源代码并改变其行为是否可行?
结论先行
你的理解完全正确,在仅使用静态import的ECMAScript模块场景下,无法通过运行时修改磁盘上的模块源码文件,影响已经加载完成的依赖图中模块的行为。
详细解释
- 首先你对CommonJS模块的描述是准确的:CommonJS的
require是运行时动态加载逻辑,模块首次被调用时才会读取磁盘文件、编译执行并缓存结果,因此只要恶意代码在目标模块被首次require前将恶意内容写入对应文件,后续的加载逻辑就会读取被篡改的版本,这也是2018年Copay钱包攻击能够生效的核心前提。 - 静态ES模块的加载逻辑和CommonJS有本质区别:
- 所有静态
import声明会在代码正式执行前被统一遍历处理,引擎会提前把整个依赖树上所有模块的源码读取到内存,编译后存储在内部的模块记录字段中 - 后续模块执行、导入引用的过程中,只会调用内存中已经存储的编译结果,不会二次读取磁盘上的源文件
- 就算运行时通过
writeFileSync之类的接口修改了磁盘上的ReedSolomonDecoder.js文件,只要该模块已经被纳入静态依赖树完成加载,后续所有对它的导入都会沿用内存中的原始版本,完全不受磁盘文件修改的影响。
- 所有静态
边界说明
上述结论仅限定在你指定的静态import场景,如果使用动态import()语法加载模块,由于动态导入是运行时触发的加载行为,若触发导入前磁盘文件已经被篡改,依然会加载恶意版本。
内容的提问来源于stack exchange,提问作者Ilya Loskutov
相关产品推荐
相关产品推荐

