关于 depguard
depguard 面向 npm 仓库,在依赖变更时对比清单和锁文件,并依据可核查信号评估风险。它提供离线确定性检查,也可显式启用注册表与软件包内容检查。
主要功能
- 01比较基准版本与依赖变更
- 02检测安装脚本与疑似拼写仿冒
- 03识别降级、版本异常和锁文件漂移
- 04可选检查注册表信息与软件包内容
- 05按依赖输出风险判定和证据
适用场景
- 01合并依赖更新前检查风险
- 02审查新增依赖的安装脚本
- 03调查软件包发布历史中的异常
MCP 相关
stdio MCP 服务提供 `guard_path`、`check_package` 和 `check_history`,用于检查仓库依赖变更、单个软件包及其发布历史。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
3收录的工具列表 · 更新于 3 天前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| base | string | 否 | 用于比较的 Git 引用(例如 HEAD~1 或标签) |
| path | string | 是 | 要检查的仓库或目录的本地路径 |
| online | boolean | 否 | 同时运行 npm registry 检查(默认值为 false;基准判定无需联网) |
| content | boolean | 否 | 同时运行内容模式:获取两个版本的 tarball,并静态比较安装时的操作面;不会安装或执行任何内容(默认值为 false) |
| base_path | string | 否 | 用于比较的基准清单集所在目录 |
详细介绍
depguard
面向 npm 仓库的 PR 阶段及依赖变更早期预警。Shai-Hulud / ChainDrop 蠕虫家族于 2026 年在 500 多个 npm 包中植入后门,通过 preinstall 投放脚本在安装时执行,并沿依赖图传播。depguard 是变更差异检查工具:给定一个仓库和一个基准(git 引用或第二组清单),它会对比 package.json 和锁文件,并根据证据对每个新增、移除和变更的依赖进行评级,然后再合并变更。
基准判定完全离线且结果确定。注册表检查(版本发布时间、发布者变更、来源证明、弃用状态)仅在显式使用 --online 标志或对应的 MCP 参数时运行;即使查询失败,也不会改变本地判定。
检查内容
| 信号 | 来源 | 规则 ID |
|---|---|---|
仓库自身的 package.json 中新增的安装脚本;如果脚本内容会获取远程代码、读取凭据或运行文档中提到的 setup.mjs 投放程序名称,则提高风险等级 | 本地 | INSTALL-SCRIPT-ADDED、INSTALL-SCRIPT-CHANGED |
| 锁文件中某个已更改的依赖被新标记为包含安装脚本;新增依赖中存在安装脚本 | 本地 | INSTALL-SCRIPT-ADDED、INSTALL-SCRIPT-PRESENT |
| 名称疑似拼写仿冒的新增依赖:与仓库自身现有依赖集及随包附带的热门名称列表(约 380 个名称)相比,编辑距离为 1(较长名称为 2) | 本地 | TYPOSQUAT-SUSPECT、TYPOSQUAT-POSSIBLE |
版本异常:静默降级、从稳定版跳至预发布版、非 semver 版本、范围扩大(扩大至 * 或 latest 风险较高)、新添加未锁定的范围 | 本地 | DOWNGRADE、PRERELEASE-JUMP、VERSION-PATTERN、RANGE-WIDENED、RANGE-UNPINNED |
| 锁文件漂移:清单已更改但锁文件未变;锁文件已更改但清单未变;同一版本的解析 URL 主机发生变化;同一版本的完整性哈希被移除或更改 | 本地 | LOCKFILE-DRIFT、LOCKFILE-ONLY-DRIFT、RESOLVED-HOST-CHANGE、INTEGRITY-REMOVED、INTEGRITY-CHANGED |
| 清单中的依赖没有对应的锁文件条目(单快照模式) | 本地 | LOCK-MISSING |
| 版本发布于 7 天以内;发布者或维护者相较于上一版本发生变化;缺少来源证明;标记为已弃用;版本未出现在注册表中 | 仅在线 | VERSION-AGE、MAINTAINER-CHANGE、NO-PROVENANCE、DEPRECATED、VERSION-NOT-FOUND |
| 两个版本 tarball 的内容差异:版本升级新增安装脚本,或在安装可执行文件中(目标脚本及其相对导入文件)新增凭据路径字符串、网络端点、二进制文件或疑似混淆代码。悄然升级并新增读取凭据路径的 preinstall 时,会判定为 HIGH-RISK 并列出新增信号;不含此类信号的正常构建 postinstall 不会被判定为高风险 | 仅内容模式(--content) | CONTENT-INSTALL-SCRIPT-ADDED、CONTENT-INSTALL-SCRIPT-CHANGED、CONTENT-CRED-SIGNAL-ADDED、CONTENT-NETWORK-ENDPOINT-ADDED、CONTENT-BINARY-ADDED、CONTENT-OBFUSCATED-ADDED |
| 注册表发布历史:分阶段蠕虫模式(0.0.0-stage 占位版本、外观像诱饵的发布版本,随后快速发布回退补丁并保持 dist-tags.latest 指向该版本)、阶段占位版本、latest 版本回退、快速回退版本集群、发布者和维护者变更、仓库 slug 变更、来源证明缺失 | 历史模式(depguard history <name>) | HISTORY-STAGED-PATTERN、HISTORY-STAGE-STUB、HISTORY-LATEST-REGRESSION、HISTORY-RAPID-REGRESSION、HISTORY-MAINTAINER-CHANGE、HISTORY-REPO-CHANGE、HISTORY-PROVENANCE-DROP、HISTORY-PACKAGE-NOT-FOUND |
锁文件:package-lock.json 会被完整解析(v1 旧版树结构及 v2/v3 packages 映射)。对于 yarn.lock 和 pnpm-lock.yaml,会尽力解析已解析的条目和版本。
判定结果:按依赖及整体给出 CLEAR / REVIEW / HIGH-RISK;每项发现都会提供一条证据,注明依赖、变更、规则 ID、严重程度,以及信号来自本地还是在线。判定为 CLEAR 时,退出代码为 0;判定为 REVIEW 或 HIGH-RISK 时,退出代码为 1。
CLI
depguard check [path] [--json] [--offline] [--online] [--content] [--base <ref>] [--base-path <dir>]
depguard package <name> [version] [--json] [--online] [--content]
depguard history <name> [--json] [--registry npm|pypi]
depguard mcp
history(v0.3.0,ledger P-159)会分析单个软件包的注册表发布历史,检查分阶段蠕虫模式及相关信号。它只读取注册表元数据,不下载 tarball。自 v0.4.0 起,--registry pypi(或 check_history 上的 registry 参数)会改为通过 JSON API 读取 PyPI 历史:相同的时间线检查(分阶段模式、阶段存根、最新版本回归、快速回归)会根据各版本的上传时间运行,此外还会针对文件全部被撤回的发布版本报告 PyPI 专属的 HISTORY-YANKED-VERSION 发现项。PyPI 不会通过该 API 发布各版本的发布者、维护者、仓库或来源数据,因此这些 npm 检查不会在 PyPI 历史上触发。
默认情况下,check 会针对当前目录运行离线核心检查,并将其视为单个快照(根据当前内容为每个清单依赖项评级)。传入 --base HEAD~1(任意 git ref)或 --base-path <dir> 可与基准进行差异比较。package 无需仓库即可为单个名称评级。JSON 报告不含时间戳,因此相同输入会产生逐字节相同的输出。
--content 会增加基于内容的更新审查(v0.2.0,ledger P-158):对于每个已更改或新增的依赖项,以及具有先前已发布版本的快照固定版本,depguard 会从 npm 注册表获取两个版本的 tarball,并静态比较安装时表面内容。tarball 只会在内存中解压:depguard 从不安装或执行 tarball 中的任何内容。在带有 --content 的 package 模式下,会将指定版本与低于它的最高已发布版本进行比较。
MCP
一个可执行文件同时提供 CLI 和 stdio MCP 服务(depguard mcp)。工具:
guard_path(path, base?, base_path?, online?, content?):以 JSON 格式返回完整差异报告。check_package(name, version?, online?, content?):为单个软件包名称和版本评级。check_history(name):分析软件包的注册表发布历史,检查分阶段模式及相关信号。
限制
- 仅处理根目录清单:v0.1.0 不会盘点嵌套工作区中的 package.json 文件和嵌套 lockfile。(Ledger P-132,已记录的限制。)
- pnpm-lock.yaml 解析基于键并尽力而为:仅当 lockfile 布局以内联形式公开已解析的 tarball URL 时才会捕获,因此已解析主机漂移检测对 package-lock.json 的支持最完善,其次是 yarn.lock,再次是 pnpm-lock.yaml。
- 依赖项自身的安装脚本仅在 lockfile 中有记录时才可知(package-lock 中的
hasInstallScript),或在联网时由注册表元数据声明。内容模式(--content,v0.2.0)更进一步,会下载两个版本的 tarball 以比较其安装时表面内容,但检查仅为静态:tarball 会在内存中解压,不会安装任何内容,也不会执行任何 tarball 代码。离线和联网模式都不会下载任何内容。 - 内容模式会跟踪安装脚本目标及其相对导入,深度为 3;依赖项自身内部图中更深处的信号,或安装时生成的信号,均不在此信号的检测范围内。
- 错别字仿冒检测仅基于名称形式。名称本身就是常见捆绑名称时,绝不会被标记(ledger P-130);而精心挑选且编辑距离为 3 或更大的名称,按设计不在此信号的检测范围内。
- 联网信号的准确性取决于注册表 packument:发布者比较使用低于当前版本的最高版本所记录的发布者;来源表示注册表元数据中存在证明条目,并不代表该证明已通过验证。
- 上限明确可见,绝不会静默生效:lockfile 解析在 50,000 个条目处停止,任何超过 64 MiB 的清单文件都会被跳过;这两种情况都会在输出中报告(JSON 中的
caps、人类可读输出中的上限提示行,以及警告)。
Development
npm install
npm run build
npm test
TypeScript、Node >= 20,使用 tsx --test 运行测试;单元测试不使用网络(注册表响应通过注入的 fixture 提供)。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。