CRBroughton/recul
GitHub: CRBroughton/recul
一个通过让npm依赖版本滞后于最新发布来降低供应链攻击风险的审计工具。
Stars: 0 | Forks: 0
# recul
让你的 npm 依赖版本滞后于最新发布版本 N 个版本,以避免供应链攻击。
recul 不能替代 `npm audit` 或第三方安全工具的常规审计;它是一个补充层,无需在每个发布周期都主动付出努力即可缩小攻击面。
## 工作原理
给定滞后 N 个版本,目标版本为 `versions[latest_index - N]`。只计算稳定版本;预发布版本(可配置,默认排除 `-alpha`、`-beta`、`-rc`、`-next`、`-canary`、`-dev`)。如果一个包的发布版本数少于滞后值,recul 会锁定到最旧的可用稳定版本。
默认情况下,已比滞后目标旧的包不会被处理。不变式是"永不太新",而不是"恰好落后 N 个"。
## 需求
- Node.js 18 或更高版本
## 安装
```
npm i -D @crbroughton/recul
# 或者
pnpm add -D @crbroughton/recul
```
## 快速开始
```
# 在当前目录创建配置文件
recul init
# 审计您的依赖项
recul
```
## 配置
提交 `recul.config.jsonc` 以在团队中统一设置。
```
{
// How many versions to stay behind the latest published release.
// Counted in releases, not semver increments.
//
// 1 → days to weeks (fast-moving projects, minimal buffer)
// 2 → weeks (balanced default, recommended)
// 3 → weeks to months (cautious teams, slower release cadences)
// 5+ → months (regulated environments, high-security contexts)
"lag": 2,
// Package manager: "npm" | "pnpm"
"packageManager": "pnpm",
// Path to the package.json to audit, relative to this config file.
"packageFile": "package.json",
// How to handle packages already older than the lag target.
// "ignore" → treat as ok, no output (default)
// "report" → surface them with a safe upgrade-to-target command
"behindBehavior": "ignore",
// Version prefix used in generated install commands.
// "exact" → 1.3.4 (recommended; audits are reliable)
// "caret" → ^1.3.4 (allows minor/patch drift)
// "tilde" → ~1.3.4 (allows patch drift only)
//
// Per-package map also supported:
// { "default": "exact", "react": "tilde" }
"rangeSpecifier": "exact",
// Packages to skip entirely.
"ignore": [],
// Minimum days a version must have been published before it is eligible
// as a lag target. Combines with "lag" for defence-in-depth.
// Omit or set to 0 to disable.
"minimumReleaseAge": 3,
// Version strings containing any of these substrings are treated as
// pre-releases and excluded from the candidate list.
"preReleaseFilter": ["-alpha", "-beta", "-rc", "-next", "-canary", "-dev"],
// Restrict the candidate list to the same major as the currently declared version.
// Prevents resolving a target across major version lines (e.g. axios 0.x vs 1.x).
// Can be a per-package map: { "default": true, "axios": false }
"sameMajor": true
}
```
需要配置文件;如果没有,请运行 `recul init`。
## CLI 参数
| 参数 | 描述 |
|------|-------------|
| `-f, --file` | `package.json` 的路径(默认:`package.json`)|
| `--fix` | 直接将 catalog 修复应用到 `pnpm-workspace.yaml` |
| `--behindBehavior=` | 覆盖配置中的 `behindBehavior`(`ignore` 或 `report`)|
## 输出
```
recul staying 2 versions behind latest
settings
lag 2 ; stay 2 versions behind latest
pm pnpm ; the chosen package manager
behind ignore ; ignore packages behind target
range exact ; pin exact versions
minAge 3 ; skip versions published within the last 3 days
package declared → target latest gap status
──────────────────────────────────────────────────────────────────────────────────────
express ^4.19.2 4.17.3 4.19.2 2 ↓ will pin back
react ^18.3.1 18.1.0 18.3.1 2 ↓ will pin back
typescript 5.4.5 5.4.5 5.4.5 0 ✓ ok
to pin back:
pnpm add express@4.17.3 react@18.1.0
```
### 状态值
| 状态 | 含义 |
|--------|---------|
| `✓ ok` | 处于或滞后于滞后目标 |
| `↓ will pin back` | 领先于滞后目标;显示安装命令 |
| `↑ safe to upgrade` | 落后于目标(仅在 `behindBehavior: report` 时显示)|
| `✗ unresolved` | 注册表获取失败或未找到稳定版本 |
当一个包使用与 `rangeSpecifier` 不同的范围前缀声明时,会附加 `⚠ declared ` 警告;这意味着审计的版本可能与实际安装的版本不同。
## pnpm catalog 支持
当使用带有 `pnpm-workspace.yaml` 中 `catalogs` 块的 pnpm 工作区时,recul 会读取 catalog 条目以解析 `package.json` 中的 `catalog:` 和 `catalog:` 引用。
Catalog 管理的包中的违规会报告需要更新的 catalog 条目,而不是安装命令。传递 `--fix` 以直接应用到 `pnpm-workspace.yaml`。
## Lockfile 支持
当存在 lockfile 时,recul 会从中读取已安装的版本并使用它进行比较,而不是声明的范围。这对于使用 `^` 或 `~` 声明的包可以给出准确的结果。
| 包管理器 | Lockfile |
|----------------|----------|
| npm | `package-lock.json` (v3) |
| pnpm | `pnpm-lock.yaml` (v6+) |
## GitHub Actions
将 recul 添加到你的 CI 流水线中,以便在依赖领先于其滞后目标时使工作流失败:
```
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- uses: CRBroughton/recul@v1
```
### 输入
| 输入 | 默认值 | 描述 |
|-------|---------|-------------|
| `working-directory` | `.` | 包含 `recul.config.jsonc` 和 `package.json` 的目录 |
| `fail-on-violations` | `true` | 设为 `false` 以进行不会失败的信息性运行 |
| `behind-behavior` | `` | 覆盖配置中的 `behindBehavior`(`ignore` 或 `report`)|
### 退出码
| 代码 | 含义 |
|------|---------|
| `0` | 所有包都在其滞后目标范围内 |
| `1` | 一个或多个包需要锁定、未解决,或(在 `behindBehavior: report` 时)落后于目标 |
标签:GNU通用公共许可证, MITM代理, Node.js, npm, pnpm, 依赖滞后, 依赖管理, 包管理器, 安全可观测性, 攻击面减少, 数据可视化, 暗色界面, 漏洞防护, 版本控制, 统一API, 自动化攻击, 软件供应链, 防御性安全