关于 dependencies-audit
用于审查和修复项目依赖问题的技能,面向需要准备 Dune 应用审查材料的开发者。它检查版本、安全漏洞、维护状况、供应链风险和许可证,并生成 `review-packages.md` 及未解决事项摘要。
主要功能
- 01盘点依赖并查询 npm 元数据
- 02检查并修复已知安全漏洞
- 03评估依赖健康状况与弃用情况
- 04审查安装脚本和供应链风险
- 05检查许可证并生成审查报告
适用场景
- 01审计项目依赖中的漏洞与过期版本
- 02查找弃用或维护状况不佳的依赖
- 03为 Dune 应用审查生成依赖清单
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ cognitedata/ dune-skills --skill dependencies-audit安装后在 Claude Code 中输入/dependencies-audit确认已加载。
详细介绍
依赖项修复
查找并修复 $ARGUMENTS 中(如果未提供参数,则为根目录 package.json)的所有依赖项问题,包括漏洞、过时的软件包、已弃用的依赖项、许可证问题和供应链风险。此技能会生成 Dune 应用审核流程所需的 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 {}
}
"
Dune 应用可接受的许可证(商业分发):
- 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”或缺失的许可证
修复:替换许可证有问题的包
对于 生产依赖项 中使用 copyleft 许可证(GPL、AGPL)或许可证未知的包,请寻找使用 MIT/Apache-2.0 许可证的替代包并将其替换。更新代码库中的所有导入。
对于使用 copyleft 许可证的 devDependencies,风险较低,但仍需标记以供注意。
每次替换后,运行 pnpm install 和 pnpm run build 进行验证。
步骤 7 — 生成 review-packages.md 工件(修复后的状态)
应用所有修复后,重新运行元数据查询,以获取修复后的状态。然后按照 Dune 应用审核流程要求的格式生成输出:
## 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 各有多少项,已解决多少个问题,以及应用作者仍需手动处理的事项。