mcpField
D
dependencies-audit

dependencies-audit

github.com/cognitedata安全61.9k 次安装1 天前更新
代码仓库

关于 dependencies-audit

dependencies-audit 用于审计并修复项目或根目录 package.json 中的依赖问题,涵盖安全、维护状态、供应链和许可证,并生成 Flows 审核所需的 review-packages.md。

主要功能

  1. 01检查依赖元数据与更新状态
  2. 02审计并修复安全漏洞
  3. 03评估健康度并替换问题包
  4. 04检查安装脚本供应链风险
  5. 05检查许可证兼容性
  6. 06生成 review-packages.md

适用场景

  1. 01为 Flows 应用准备审核材料
  2. 02查找并修复依赖漏洞
  3. 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列出软件包及版本变更
已解决的 CVEN列出已修复的 CVE
已替换的弃用依赖项N旧软件包 -> 新软件包
已解决的许可证问题N旧软件包 -> 新软件包
剩余问题(无法自动修复)

仅列出无法自动修复的问题:

  • 重大版本更新带来的破坏性变更,需要手动调整代码
  • 需要进行法律审查的许可证(例如,传递依赖项中的 LGPL)
  • 没有可维护替代项的软件包
  • 尚无已修补版本的漏洞

对于每个剩余问题,说明无法自动修复的原因,以及应用作者需要采取的措施。


完成

给出总体健康状况结论:修复后有多少项 Pass/Warn/Fail,解决了多少个问题,以及有哪些仍需应用作者手动处理的事项。

评论

支持 Markdown