开源信任一直建立在一个简单的前提上:代码你能读,所以你能自己判断。当你直接从作者那里安装,这个前提成立;一旦作者和你之间插入了一层插件分发环节,它就明显变弱——你装到的东西已经不完全是作者发布的那个东西。插件分发风险主要不是来自恶意作者,而是来自那些在你机器上之前会重新打包、镜像、缓存或重新评分插件的、不起眼的中间环节,以及一旦它们存在,验证插件来源这件事会变得多难。
你实际接受的信任链
装一个插件,你就接受了一条至少四环的链。
| 环节 | 谁控制 | 可能与源不一致的地方 |
|---|---|---|
| 源仓库 | 作者 | 无,这是基准 |
| 注册表 / 索引 | 平台方 | 元数据、标签、版本排序 |
| 镜像 / CDN | 托管方 | 缓存的文件、陈旧版本 |
| 安装脚本 | 插件或包装方 | 额外下载、安装后步骤 |
每一环都可以是善意的,仍然会产出一个和你读过的仓库不完全一致的结果。上个月的缓存包不是恶意的,但它也不是你刚看过 changelog 的那个版本。
中间人究竟在哪一层
这个词涵盖几种不同角色,风险各不相同。
- 聚合站点收录自己并不维护的插件。价值在发现,风险在列表数据会过期,而且没人负责更正。
- 包装包依赖真正的插件再加一层配置。方便,但你要信任的维护者从一个变成两个。
- 镜像是公司内为网络或合规原因搭建的。快,也是版本漂移的安静来源。
- 安装脚本在安装时才拉取,而不是打包在包里。包本身可以干净,脚本半年后干的事可以完全不同。
四种不算攻击的失效方式
现实里多数麻烦来自疏忽,不是恶意。
- 版本漂移:索引显示 2.4.1,镜像给的是 2.3.8,你的锁文件记录的又是另一个。没有任何东西明确报错。
- 包装包被弃:上游插件还在维护,包装包两年没动,还钉在旧 API 上。
- 元数据注水:标签和分类往往是提交列表的人写的,不是作者。搜索结果于是反映营销,而不是功能。
- 安装时拉取:插件在安装过程中下载自身的一部分,信任边界就落在你无法从包内容里审查的地方。
中间方可以不通知你就改的三件事
具体来说是三件:你拿到哪个版本、用什么元数据描述它、下载完成后执行什么。这三件都不需要拿到作者仓库的写权限,这也正是仓库侧的安全工作覆盖不到它们的原因。
签名提交证明作者发布过那个提交,不证明你装的东西是由它构建出来的。
十分钟检查一遍信任链
- 把索引里的版本和源仓库最新 release 对一下。不一致就先弄清楚再装。
- 运行安装脚本之前先读一遍,优先选把脚本打包进包里的,而不是运行时拉取的。
- 找找有没有包装层。如果你安装的名字和仓库上的名字不一样,你就多加了一个维护者。
- 看产物的最后发布时间,不是仓库的最后提交时间。
- 确认注册表上的维护者身份和仓库上的是同一个。
独立评分在这里改变了什么
由分发方自己算的分数,衡量的是分发,不是可信度。独立评分看的是产物本身:发布的版本和仓库是否一致、安装路径是否可审查、产物多久没变过。这也是为什么自报评分长期会往上飘,而独立评分保持平稳。这个差值本身就是信号。
挑出你的环境最依赖的三个插件,到 dshquality.com 把上面每一环过一遍。背后的评分方法见 /blog/why-independent-plugin-scoring-beats-self-reported-ratings,完整索引在 /。