2024年,一个工程师偶然发现SSH登录慢了500毫秒,顺藤摸瓜揪出了几乎成功的xz-utils供应链后门。这件事给所有开发者敲了警钟:你手头那五到十个副项目,依赖包可能正在悄无声息地腐烂,而传统的安全工具根本看不见。
Snyk、Dependabot这类工具只会追着已公开的CVE编号跑,但真正的供应链攻击在爆发前往往同时亮起三盏红灯:活跃高危漏洞、维护者弃坑、下载量断崖式下跌。这三股信号碰头时,风险就已成形,可市面上没有一个工具能把它们聚合到一块儿——直到有人用 Coral 写了一条 SQL 查询。
这条查询花了六天打磨,最终在一个语句里联查了三套实时系统:Google 的 OSV 漏洞库、npm 包注册表,以及 npm 下载统计 API。三个不同主机,零胶水代码,出来的结果就是一个包的三维风险快照。举个例子,minimist 这个 npm 包,直接查出 2 个已知 CVE,最高严重级别 CRITICAL,月下载量却有 5.31 亿次——典型的高悬顶炸弹。
查询逻辑本身并不复杂:先用 CTE 从 npm 注册表捞出包名、最新版本和最后发布时间;再去 OSV 按包名聚合 CVE 数量,同时取最高严重度对应的等级序号;再从 npm 下载 API 拿一个月内的下载量;最后左连接拼成一行。问题全出在实现细节上。
第一天就卡在了 OSV 数据源的定义文件上。Coral 允许用一个 YAML 文件描述外部 REST API 的返回结构,骨架写得很快,但真跑起来才发现两个坑。其一是自动扁平化并不存在——原本以为 database_specific 下的 severity 字段用双下划线命名 database_specific__severity 就能直接映射,结果始终返回 null。非得在 YAML 里显式写一个 expr,用 path 指定 [database_specific, severity] 才能正确提取。其二更隐蔽:受影响包的名字藏在 affected 数组的第一个元素里,取这个字段时,path 要写成 [affected, "0", package, name]——索引得用字符串 “0”,用整数 0 会直接触发 schema 校验失败。
coral source lint 能拦住 YAML 结构上的明显错误,但这些嵌套路径的匹配偏差,只能在对着真实包(比如 lodash、minimist)跑完查询、把返回的字段和 spec 一行行手动比对时才会暴露。没有任何自动化提示,全靠人肉 diff。
第二天面对的是 npm 数据源,这里让作者直呼学到了最多。因为 npm 实际上需要对接的远不止一个端点,后续的曲折让他进一步看清,跨多个 API 对齐包名和统计口径这件事,里面的坑比写 YAML 多得多。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.