- 应用安全
- 供应链安全
- 漏洞扫描
- 开发工具
【免费下载链接】DependencyCheck
OWASP dependency-check is a software composition analysis utility that detects publicly disclosed vulnerabilities in application dependencies.
导读
本指南围绕 OWASP dependency-check 的Node Package Analyzer(Node 包分析器)展开,讲解它如何通过扫描package.json、package-lock.json与npm-shrinkwrap.json三类 npm 包描述文件,为 Node.js 项目构建软件物料清单(bill-of-materials, BOM),并与 Node Audit Analyzer 协同完成已知漏洞的检测。读完本文,你将掌握该分析器的扫描范围、内部解析逻辑、配置开关、最佳实践以及各类依赖边角场景的处理方式。
分析器定位:Node.js 依赖清单的"信息采集员"
Node Package Analyzer 是 OWASP dependency-check 众多分析器(analyzer)之一,其核心职责是从 npm 的包规范文件中抽取依赖信息,生成每个 Node.js 模块的 Dependency 对象,为后续的漏洞匹配(如 NVD CPE 匹配、Node Audit、OSS Index)提供数据基础。
它的设计意图非常明确:与分析器配合,为 Node.js 项目创建一份完整的软件物料清单(BOM)。其中:
- Node Package Analyzer:负责解析包规范文件,把依赖树"展开"成一个个依赖项(名称、版本、生态、证据、purl 标识等);
- Node Audit Analyzer:负责将
package-lock.json提交给 npm audit API,返回安全公告(advisory)并注入到报告中。
二者的关系在原文档中被称为"协同工作(works in conjunction)",从源码看这种协同是强耦合的:Node Package Analyzer 在初始化时(prepareFileTypeAnalyzer,见 NodePackageAnalyzer.java)会校验 Node Audit Analyzer 或 OSS Index Analyzer 是否启用,若二者都未启用,会直接抛出初始化异常:
Invalid Configuration: enabling the Node Package Analyzer without using the Node Audit Analyzer or OSS Index Analyzer is not supported.
也就是说,单靠 Node Package Analyzer 只能产出"清单",真正的漏洞判定必须依赖后续的审计类分析器,这是使用本功能前必须理解的整体架构。
扫描范围:三类 npm 包规范文件
原文档明确列出了该分析器扫描的文件类型:
package.json:npm 的包描述文件(项目自身元数据 + 直接依赖声明);package-lock.json:npm v5+ 生成的锁文件,锁定完整依赖树;npm-shrinkwrap.json:可发布、可共享的锁文件变体。
在源码中,这三类文件通过统一的文件过滤器注册(NodePackageAnalyzer.java):
private static final FileFilter PACKAGE_JSON_FILTER = FileFilterBuilder.newInstance() .addFilenames(PACKAGE_JSON, PACKAGE_LOCK_JSON, SHRINKWRAP_JSON).build();对应的三个常量分别是package.json、package-lock.json、npm-shrinkwrap.json(见同文件 L88-L96)。单测testSupportsFiles也验证了analyzer.accept(new File("package-lock.json"))与npm-shrinkwrap.json均返回true(见 NodePackageAnalyzerTest.java)。
需要注意两个重要边界:
- 不扫描
node_modules内部:分析器继承自AbstractNpmAnalyzer,其shouldProcess方法会检查文件的规范路径(canonical path),凡是包含/node_modules/或/bower_components/的路径都会被跳过(AbstractNpmAnalyzer.java)。原因在于:锁文件已经固化了依赖树,无需再遍历磁盘上的模块副本,这既避免重复扫描,也大幅降低扫描量。 - 对
package.json的去重处理:当同一目录下同时存在锁文件时,package.json的分析会被跳过——因为锁文件包含更精确、完整的依赖树(NodePackageAnalyzer.java)。优先级为:npm-shrinkwrap.json>package-lock.json>package.json。
工作流程:从锁文件到依赖对象
分析器在INFORMATION_COLLECTION(信息采集)阶段运行,其核心处理入口是analyzeDependency与递归方法processDependencies(NodePackageAnalyzer.java)。整体流程可概括为五步:
前置校验:文件必须非空且不在
node_modules内部;若启用了 Node Audit 且当前分析的是package.json(而非锁文件),则直接将其从依赖列表中移除(engine.removeDependency),避免与锁文件重复。锁文件检查:若目录下既没有
package-lock.json、npm-shrinkwrap.json,也没有yarn.lock,会输出警告并提示潜在误报(false negatives):No lock file exists - this will result in false negatives; please run
npm install --package-lock同时,若
node_modules目录不存在,也会给出提示:请先执行npm install再运行 dependency-check(L251-L256)。解析 JSON:使用 Jakarta JSON 读取器解析文件内容,提取项目自身的
name与version,作为"父包"标识(parentPackage)。递归展开依赖树:
processDependencies根据lockfileVersion选择解析路径:lockfileVersion >= 2:读取顶层packages对象(npm v7+ 的扁平化结构,v2/v3 均适用);lockfileVersion == 1或缺失:读取dependencies对象;- 两者皆无:跳过处理。
对于每个依赖项,分析器会定位其在
node_modules下的实际模块目录,读取该模块的package.json,并递归处理其嵌套dependencies,从而覆盖传递依赖。构造 Dependency 对象:为每个模块创建 Dependency(带
rootFile?ref/name:version形式的虚拟文件路径),设置生态为Ecosystem.NODEJS、计算 MD5/SHA1/SHA256 校验和、调用gatherEvidence采集证据,并生成pkg:npm/<name>@<version>形式的 Package URL(purl)软件标识。
单测testAnalyzeShrinkwrapJson验证了传递依赖的展开:扫描npm-shrinkwrap.json后,braces与expand-range(braces的传递依赖)均出现在依赖列表中(见 NodePackageAnalyzerTest.java)。
证据采集:package.json 中哪些字段会被利用
gatherEvidence(定义于 AbstractNpmAnalyzer.java)负责从每个模块的package.json中提取证据,供后续 CPE/NVD 匹配使用:
| package.json 字段 | 证据类型 | 用途说明 |
|---|---|---|
name | VENDOR / PRODUCT | 模块名,同时以<name>_project形式补充厂商证据 |
description | VENDOR | 模块描述 |
author | VENDOR | 作者信息(不存在时回退到maintainers) |
maintainers | VENDOR | 维护者列表 |
homepage | VENDOR | 项目主页 |
bugs | VENDOR | Bug 跟踪地址 |
version | VERSION | 版本号,并生成 npm 类型 purl |
license | — | 写入依赖的许可证信息(支持字符串、数组、对象三种形态) |
从源码注释可以看到一个重要的取舍:description 只作为 VENDOR 证据加入,避免参与 CPE 分析,因为描述文本容易造成大量误报(L326 的 TODO 注释)。这解释了为什么 Node 生态的漏洞匹配更多依赖 Node Audit / OSS Index 而非 NVD CPE。
配置项与默认值
启用开关
分析器默认启用,对应配置项定义在 Settings.java:
analyzer.node.package.enabled:是否启用 Node Package Analyzer,默认true(见 dependencycheck.properties);analyzer.node.package.skipdev:是否跳过devDependencies(开发依赖),默认false。
在 CLI 中可通过--enable/--disable或属性文件覆盖;Maven 插件则通过<analyzerNodePackageEnabled>等参数配置。若禁用了 Node Package Analyzer 而仅保留 Node Audit,源码会提示:报告中将只包含已知漏洞依赖,而不再包含 Node 项目的完整物料清单(AbstractNpmAnalyzer.java)。
关联分析器配置
由于 Node Package Analyzer 强依赖审计类分析器,以下几个默认配置与之直接相关(dependencycheck.properties):
analyzer.node.audit.enabled=true:Node Audit Analyzer,默认启用,需联网访问 npm audit API;analyzer.node.audit.url=https://registry.npmjs.org/-/npm/v1/security/audits:审计 API 地址;analyzer.node.audit.use.cache=true:审计结果缓存;analyzer.ossindex.enabled=true:OSS Index Analyzer,默认启用。
源码中的初始化校验逻辑(NodePackageAnalyzer.java)进一步细化了三种组合场景:
- Node Package + Node Audit 都未启用,仅用 OSS Index:提示 Node.js 使用 OSS Index 可能产生大量误报,建议启用 Node Audit Analyzer;
- 跳过 Node 生态的 CPE 分析且未启用 OSS Index 与 Node Audit:直接抛出初始化异常,拒绝运行;
- 跳过 Node 生态 CPE 且 Node Audit 未启用:若缺少
package-lock.json/npm-shrinkwrap.json,抛出异常:Missing package.lock or npm-shrinkwrap.lock file: Unable to scan a node project without a package-lock.json or npm-shrinkwrap.json.
依赖边角场景与跳过规则
shouldSkipDependency(NodePackageAnalyzer.java)定义了哪些依赖不进入清单,这是实战中经常遇到的坑:
- npm 别名(alias):版本以
npm:开头(如npm:@hot-loader/react-dom)会被跳过,因为npm audit不支持别名,源码会记录警告package.json contain an alias ... npm audit doesn't support aliases; - 可选但未安装的模块:
optional: true且磁盘上不存在对应package.json时跳过(如fsevents仅在 macOS 安装,非 Mac 平台扫描时被跳过——单测testLock中对此有显式断言,见 NodePackageAnalyzerTest.java); - 本地模块引用:版本以
file:开头或以./~开头的相对路径(如file:fake_submodule),npm audit 不支持本地引用模块,直接跳过(单测同样验证了fake_submodule不应出现,L197-L199); - 空名称:
name为空的条目跳过(常见于 package-lock v2+ 中的根""条目); - 链接依赖(link):
link: true的条目跳过,避免后续解析崩溃。
此外,若启用了analyzer.node.package.skipdev=true,dev: true的开发依赖也会被过滤。
依赖去重与合并
依赖树展开后,同一模块可能被多个父包引用。分析器通过findDependency(按生态 + 名称 + 版本匹配,AbstractNpmAnalyzer.java)查找已存在的依赖,再进行合并(NodePackageAnalyzer.java):
- 已存在的是虚拟依赖(virtual):调用
DependencyMergingAnalyzer.mergeDependencies合并后替换; - 已存在的是真实依赖:调用
DependencyBundlingAnalyzer.mergeDependencies归并,将新引用作为 project reference 追加。
因此最终报告中每个 npm 模块只出现一次,但会记录它被哪些项目/作用域引用,便于追溯调用关系。
最佳实践总结
结合原文档与源码,使用 Node Package Analyzer 的推荐姿势如下:
- 务必提交锁文件:
package-lock.json或npm-shrinkwrap.json是准确构建 BOM 的前提。缺失锁文件时分析器会输出误报警告,且部分场景下直接拒绝初始化(配置了 skip-ecosystem 时)。 - 扫描前执行
npm install:分析器需要读取node_modules下各模块的package.json来计算校验和与采集证据;目录缺失时会跳过分析。 - 保持 Node Audit Analyzer 启用:默认即启用(需联网)。仅依赖 OSS Index 可能引入大量误报;两者都关闭则无法完成 Node 项目的漏洞判定。
- 合理使用
skipdev:若只关心生产依赖的漏洞,可开启analyzer.node.package.skipdev以缩小扫描范围、加快速度。 - 注意别名与本地依赖的局限:
npm:别名、file:本地模块、可选未安装模块不会被纳入清单,这是 npm audit 生态的固有边界,需要在报告中结合人工审计补充。
验证与进一步阅读
- 分析器实现:NodePackageAnalyzer.java
- 公共抽象基类(证据采集、purl 生成、去重):AbstractNpmAnalyzer.java
- 单元测试(覆盖 v1/v2/v3 锁文件、无锁文件、本地依赖、别名跳过等场景):NodePackageAnalyzerTest.java
- 默认配置:dependencycheck.properties
- 配套分析器文档:Node Audit Analyzer;分析器总览见 analyzers/index.md
总而言之,Node Package Analyzer 是 dependency-check 在 JavaScript 生态中的"清单构建引擎":它把 npm 的声明文件转化为结构化、可追溯、带 purl 标识的依赖集合,再交由 Node Audit 与 NVD/OSS Index 完成漏洞判定。理解其扫描边界、配置联动与跳过规则,是在 CI 中准确落地 Node.js 软件成分分析(SCA)的关键一步。
- 应用安全
- 供应链安全
- 漏洞扫描
- 开发工具
【免费下载链接】DependencyCheck
OWASP dependency-check is a software composition analysis utility that detects publicly disclosed vulnerabilities in application dependencies.
相关推荐
如何5分钟掌握res-downloader:解锁全网视频音乐图片资源下载神器
如何5分钟掌握res downloader:解锁全网视频音乐图片资源下载神器 还在为无法下载微信视频号、抖音无水印视频、QQ音乐等平台资源而烦恼吗?res do
桌面应用网络音视频推荐文章:OWASP Dependency-Check —— 构建安全的软件依赖环境
推荐文章:OWASP Dependency Check —— 构建安全的软件依赖环境 在当今快速发展的软件行业,安全性已成为软件开发不可或缺的一部分。OWASP
漏洞扫描应用安全供应链安全开发工具OWASP Dependency-Check与Grafana集成:构建依赖安全监控仪表盘
OWASP Dependency Check与Grafana集成:构建依赖安全监控仪表盘 OWASP Dependency Check是一款强大的软件成分分析工
应用安全供应链安全漏洞扫描开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考