关于 dependencies-audit
dependencies-audit 用于审计并修复项目或根目录 package.json 中的依赖问题,涵盖安全、维护状态、供应链和许可证,并生成 Flows 审核所需的 review-packages.md。
主要功能
- 01检查依赖元数据与更新状态
- 02审计并修复安全漏洞
- 03评估健康度并替换问题包
- 04检查安装脚本供应链风险
- 05检查许可证兼容性
- 06生成 review-packages.md
适用场景
- 01为 Flows 应用准备审核材料
- 02查找并修复依赖漏洞
- 03在商业分发前检查包许可证
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ cognitedata/ builder-skills --skill dependencies-audit安装后在 Claude Code 中输入/dependencies-audit确认已加载。
详细介绍
依赖项修复
查找并修复 $ARGUMENTS 中的所有依赖项问题(如果未提供参数,则检查根目录下的 package.json)——包括漏洞、过时的包、已弃用的依赖项、许可证问题和供应链风险。此技能会生成 Flows 应用审核流程所需的 review-packages.md 产物。
第 1 步 — 读取并列出所有依赖项
# List all dependencies and devDependencies
node -e "
const pkg = require('./package.json');
console.log('=== Dependencies ===');
Object.entries(pkg.dependencies || {}).forEach(([name, ver]) => console.log(name + ' @ ' + ver));
console.log('\\n=== Dev Dependencies ===');
Object.entries(pkg.devDependencies || {}).forEach(([name, ver]) => console.log(name + ' @ ' + ver));
"
记录 dependencies 和 devDependencies 的总数。
第 2 步 — 查询 npm 元数据并更新过时的包
对于每个包,收集:
- npm 上的最新版本
- 每周下载量
- 最后发布时间
- 已弃用标记
# Batch lookup — run for each package (example for a single package)
npm view <package-name> --json 2>/dev/null | node -e "
const data = JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));
console.log(JSON.stringify({
name: data.name,
latest: data['dist-tags']?.latest,
modified: data.time?.modified,
deprecated: data.deprecated || false,
}));
"
# For weekly downloads, use the npm API
curl -s "https://api.npmjs.org/downloads/point/last-week/<package-name>" | node -e "
const data = JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));
console.log(data.downloads);
"
为提高效率,可批量查询。如果项目有许多依赖项,请使用脚本:
node -e "
const { execSync } = require('child_process');
const pkg = require('./package.json');
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
for (const [name, usedVersion] of Object.entries(allDeps)) {
try {
const info = JSON.parse(execSync('npm view ' + name + ' --json 2>/dev/null', { encoding: 'utf8' }));
const latest = info['dist-tags']?.latest || 'unknown';
const modified = info.time?.modified || 'unknown';
const deprecated = info.deprecated ? 'YES' : 'No';
console.log([name, usedVersion, latest, modified, deprecated].join(' | '));
} catch {
console.log(name + ' | ' + usedVersion + ' | LOOKUP FAILED');
}
}
"
修复:更新过时的包
对于落后超过 1 个主版本的包,进行更新:
pnpm update <package>@latest
对于落后 1 个或更多次要版本的包,更新到最新次要版本:
pnpm update <package>
更新后,运行 pnpm install 和 pnpm run build,验证没有破坏任何内容。如果主版本更新导致构建失败,请还原该特定更新,并将其列为需要手动修复的项目。
第 3 步 — 运行安全审计并修复漏洞
# Run audit with the project's package manager
pnpm audit --json 2>/dev/null || npm audit --json 2>/dev/null
# Also run production-only audit (what ships to users)
pnpm audit --prod --json 2>/dev/null || npm audit --production --json 2>/dev/null
解析 JSON 输出,获取:
- 严重性计数(critical、high、moderate、low)
- 每个漏洞的详细信息(包、严重性、标题、修复版本、公告 URL)
任何存在已知 CVE 的包,在健康状态列中都自动标记为 Fail。
修复:解决漏洞
运行 pnpm audit fix,自动修复可修复的问题。对于仍无法自动修复的高危或严重 CVE,在 package.json 中手动将存在漏洞的包更新到已修复版本,然后运行 pnpm install。如果已修复版本存在不兼容更改,请进行适配所需的最小代码更改。如果漏洞存在于传递依赖中,请在 package.json 中使用 pnpm overrides 强制使用已修复版本:
{
"pnpm": {
"overrides": {
"vulnerable-package": ">=2.1.0"
}
}
}
应用修复后,重新运行 pnpm audit,确认漏洞已解决。运行 pnpm run build,验证没有破坏任何内容。
第 4 步 — 评定健康状态并修复标记为 Fail 的包
为每个包分配一个健康状态:
| 健康状态 | 标准 |
|---|---|
| Pass | 每周下载量 >100k,且在过去 12 个月内更新过、未弃用,版本为当前版本或接近当前版本(相差不超过 1 个主版本) |
| Warn | 每周下载量为 10k–100k,或距离上次发布已超过 12 个月,或落后超过 1 个主版本 |
| Fail | 每周下载量 <10k,或 2 年及以上未更新,或已弃用,或存在已知 CVE |
特殊情况:
@cognite/*包:即使下载量较低,也信任 Cognite 内部包@types/*包:信任 DefinitelyTyped 包;重点检查版本是否与主包匹配- 新发布的包(发布不到 6 个月):标记为 Warn 以供审核,不因下载量低而自动标记为 Fail
修复:替换标记为 Fail 的包
对于每个标记为 Fail 的包:
- **如果已弃用:**查找并安装推荐的替代包。更新代码库中的所有导入。
- **如果已停止维护(2 年及以上):**查找功能相当且仍在积极维护的替代方案,并替换该包。
- **如果下载量低且不属于
@cognite/*:**评估是否确实需要该包。如果存在原生 JS/TS 等效方案,或功能较简单,则移除该依赖并以内联方式实现。
每次替换后,运行 pnpm install 和 pnpm run build,验证替代方案有效。
第 5 步 — 检查供应链风险并降低风险
# Check for install scripts (preinstall, postinstall, prepare)
node -e "
const { execSync } = require('child_process');
const pkg = require('./package.json');
const allDeps = Object.keys({ ...pkg.dependencies, ...pkg.devDependencies });
for (const name of allDeps) {
try {
const info = JSON.parse(execSync('npm view ' + name + ' --json 2>/dev/null', { encoding: 'utf8' }));
const scripts = info.scripts || {};
const risky = ['preinstall', 'install', 'postinstall'].filter(s => scripts[s]);
if (risky.length > 0) {
console.log('INSTALL SCRIPT: ' + name + ' — ' + risky.join(', '));
}
} catch {}
}
"
# Check for packages with very few maintainers (single point of failure)
# This is informational, not blocking
修复:评估并降低安装脚本风险
对于每个包含安装脚本的依赖项,判断该脚本是否合法(例如,sharp、esbuild、better-sqlite3 的原生模块编译)。已知构建工具和原生模块包通常会包含安装脚本。
如果该包不是已知的构建工具,且其安装脚本可疑,请将其替换为更安全的替代方案。替换后,运行 pnpm install 和 pnpm run build,验证替代方案有效。
第 6 步 — 检查许可证兼容性并替换存在问题的软件包
# List all licenses
npx license-checker --summary 2>/dev/null || node -e "
const { execSync } = require('child_process');
const pkg = require('./package.json');
const allDeps = Object.keys({ ...pkg.dependencies, ...pkg.devDependencies });
for (const name of allDeps) {
try {
const info = JSON.parse(execSync('npm view ' + name + ' --json 2>/dev/null', { encoding: 'utf8' }));
console.log(name + ': ' + (info.license || 'UNKNOWN'));
} catch {}
}
"
Flows 应用可接受的许可证(商业分发):
- MIT、Apache-2.0、BSD-2-Clause、BSD-3-Clause、ISC、0BSD、Unlicense、CC0-1.0
需要进行法律审查的许可证:
- GPL-2.0、GPL-3.0、LGPL-2.1、LGPL-3.0、AGPL-3.0、MPL-2.0、EUPL-1.1
- 任何“UNKNOWN”或缺失的许可证
修复:替换许可证存在问题的软件包
对于 生产依赖项 中采用著作权传染型许可证(GPL、AGPL)或许可证未知的软件包,请寻找采用 MIT/Apache-2.0 许可证的替代项并进行替换。更新整个代码库中的所有导入。
对于采用著作权传染型许可证的 devDependencies,风险较低,但仍需标记以便知悉。
每次替换后,运行 pnpm install 和 pnpm run build 进行验证。
第 7 步 — 生成 review-packages.md 产物(修复后状态)
应用所有修复后,重新查询元数据,以获取修复后的状态。然后按照 Flows 应用审核流程要求的格式生成输出:
## Package audit: [app name]
### Dependencies
| Package | Used version | Latest | Weekly downloads | Last published | Deprecated | CVEs | Health |
| ------- | ------------ | ------ | ---------------- | -------------- | ---------- | ---- | ------ |
| react | ^18.2.0 | 18.3.1 | 25M | 2024-04-26 | No | 0 | Pass |
| some-old-lib | ^1.0.0 | 1.0.3 | 5k | 2021-03-15 | No | 0 | Fail |
### Dev Dependencies
| Package | Used version | Latest | Weekly downloads | Last published | Deprecated | CVEs | Health |
| ------- | ------------ | ------ | ---------------- | -------------- | ---------- | ---- | ------ |
| vitest | ^1.6.0 | 2.0.1 | 8M | 2024-07-01 | No | 0 | Pass |
### Security audit
| Severity | Count |
| -------- | ----- |
| Critical | 0 |
| High | 0 |
| Moderate | 0 |
| Low | 0 |
#### Vulnerabilities
| Package | Severity | Title | Patched in | Advisory |
| ------- | -------- | ----- | ---------- | -------- |
| (none found) | — | — | — | — |
### License summary
| License | Count | Packages |
| ------- | ----- | -------- |
| MIT | 45 | react, react-dom, ... |
| Apache-2.0 | 3 | ... |
### Supply-chain flags
| Package | Risk | Details |
| ------- | ---- | ------- |
| (none found) | — | — |
第 8 步 — 报告剩余问题
总结已修复的内容和剩余问题:
已修复
| 类别 | 数量 | 详情 |
|---|---|---|
| 已更新的软件包 | N | 列出软件包及版本变更 |
| 已解决的 CVE | N | 列出已修复的 CVE |
| 已替换的弃用依赖项 | N | 旧软件包 -> 新软件包 |
| 已解决的许可证问题 | N | 旧软件包 -> 新软件包 |
剩余问题(无法自动修复)
仅列出无法自动修复的问题:
- 重大版本更新带来的破坏性变更,需要手动调整代码
- 需要进行法律审查的许可证(例如,传递依赖项中的 LGPL)
- 没有可维护替代项的软件包
- 尚无已修补版本的漏洞
对于每个剩余问题,说明无法自动修复的原因,以及应用作者需要采取的措施。
完成
给出总体健康状况结论:修复后有多少项 Pass/Warn/Fail,解决了多少个问题,以及有哪些仍需应用作者手动处理的事项。