Skip to content
Go back

PNPM 项目安全漏洞批量修复完整指南

Published:  at  10:22 PM

PNPM 项目安全漏洞批量修复完整指南

本文记录了在使用 PNPM 管理的项目中,如何系统性地发现和修复依赖包安全漏洞的完整过程。

📋 目录


问题背景

在项目开发过程中,使用 dependency-check 工具扫描项目依赖时,发现了多个安全漏洞警告。这些漏洞主要来自间接依赖(transitive dependencies),直接更新 package.json 无法解决。

环境信息


问题发现

第一步:使用工具扫描

使用 OWASP dependency-check 工具扫描项目:

dependency-check --project "MyProject" --scan pnpm-lock.yaml

发现典型漏洞示例:

示例 1: Lodash 原型污染漏洞

┌─────────────────────┬────────────────────────────────────────────┐
│ CVE-2025-13465      │ Lodash Prototype Pollution                 │
├─────────────────────┼────────────────────────────────────────────┤
│ Package             │ lodash                                     │
├─────────────────────┼────────────────────────────────────────────┤
│ Vulnerable versions │ 4.0.0 - 4.17.22                           │
├─────────────────────┼────────────────────────────────────────────┤
│ Patched versions    │ ≥4.17.23                                  │
├─────────────────────┼────────────────────────────────────────────┤
│ Severity            │ MEDIUM (CVSS 6.5)                         │
└─────────────────────┴────────────────────────────────────────────┘

示例 2: minimatch ReDoS 漏洞

┌─────────────────────┬────────────────────────────────────────────┐
│ GHSA-3ppc-4f35-3m26 │ minimatch ReDoS via repeated wildcards     │
├─────────────────────┼────────────────────────────────────────────┤
│ Package             │ minimatch                                  │
├─────────────────────┼────────────────────────────────────────────┤
│ Vulnerable versions │ <3.1.3 或 >=9.0.0 <9.0.7                  │
├─────────────────────┼────────────────────────────────────────────┤
│ Patched versions    │ ≥3.1.4 或 ≥9.0.7                          │
├─────────────────────┼────────────────────────────────────────────┤
│ Severity            │ HIGH                                       │
└─────────────────────┴────────────────────────────────────────────┘

示例 3: Rollup 路径遍历漏洞

┌─────────────────────┬────────────────────────────────────────────┐
│ GHSA-mw96-cpmx-2vgc │ Rollup 4 Arbitrary File Write              │
├─────────────────────┼────────────────────────────────────────────┤
│ Package             │ rollup                                     │
├─────────────────────┼────────────────────────────────────────────┤
│ Vulnerable versions │ >=4.0.0 <4.59.0                           │
├─────────────────────┼────────────────────────────────────────────┤
│ Patched versions    │ ≥4.59.0                                   │
├─────────────────────┼────────────────────────────────────────────┤
│ Severity            │ HIGH                                       │
└─────────────────────┴────────────────────────────────────────────┘

第二步:尝试使用 pnpm audit

pnpm audit

遇到第一个障碍

ERR_PNPM_AUDIT_ENDPOINT_NOT_EXISTS
The audit endpoint (at https://registry.npmmirror.com/-/npm/v1/security/audits) doesn't exist.
This issue is probably because you are using a private npm registry.

问题原因: 淘宝镜像源不支持 audit 端点


问题分析

漏洞分类统计

严重程度数量主要影响包
High9minimatch, rollup, immutable, flatted
Moderate3ajv, dompurify
Low2qs, @tootallnate/once

依赖关系分析

大部分漏洞来自间接依赖(开发依赖的依赖):

# 查看 minimatch 的依赖路径
pnpm why minimatch

# 输出示例
minimatch 3.0.8
└─── @jest/core 27.0.6
     └─── @jest/reporters 27.0.6
          └─── glob 7.1.7
               └─── minimatch 3.0.8 (vulnerable)

关键发现

  1. 这些包不在项目的 package.json
  2. 是其他依赖包的间接依赖
  3. 直接更新 package.json 无法解决
  4. 需要使用 overrides 机制强制更新

解决方案

方案 1: 临时切换源进行审计(推荐)

由于淘宝镜像不支持 audit,切换到官方源:

# 方法 1: 临时使用官方源
npm audit --registry=https://registry.npmjs.org/

# 方法 2: 环境变量方式
npm_config_registry=https://registry.npmjs.org/ pnpm audit

方案 2: 配置 .npmrc(推荐)

在项目根目录创建/编辑 .npmrc 文件:

# .npmrc
# 日常安装使用淘宝镜像加速
registry=https://registry.npmmirror.com/

# 审计时使用官方源
audit-registry=https://registry.npmjs.org/

# 其他加速配置
sharp_binary_host=https://npmmirror.com/mirrors/sharp
electron_mirror=https://npmmirror.com/mirrors/electron/

优势: 一次配置,后续可直接使用 pnpm audit

方案 3: 使用 PNPM Overrides(核心方案)

PNPM 的 overrides 功能可以强制所有依赖使用指定版本:

{
  "pnpm": {
    "overrides": {
      "lodash": "^4.17.23",
      "minimatch": "^9.0.7",
      "rollup": "^4.59.0",
      "immutable": "^5.1.5",
      "flatted": "^3.4.0",
      "ajv": "^8.18.0",
      "dompurify": "^3.3.2",
      "qs": "^6.14.2",
      "@tootallnate/once": "^3.0.1"
    }
  }
}

完整修复流程

步骤 1: 备份现有配置

# 备份 package.json
cp package.json package.json.backup

# 备份 pnpm-lock.yaml
cp pnpm-lock.yaml pnpm-lock.yaml.backup

步骤 2: 配置审计源

创建或编辑 .npmrc

echo "registry=https://registry.npmmirror.com/" > .npmrc
echo "audit-registry=https://registry.npmjs.org/" >> .npmrc

步骤 3: 执行安全审计

# 使用官方源进行审计
npm audit --registry=https://registry.npmjs.org/

# 或者如果配置了 .npmrc
pnpm audit

步骤 4: 分析漏洞并确定修复版本

根据审计结果,整理需要修复的包:

包名当前版本安全版本修复版本
lodash4.17.21≥4.17.23^4.17.23
minimatch3.0.8 / 9.0.5≥3.1.4 / ≥9.0.7^9.0.7
rollup4.20.0≥4.59.0^4.59.0
immutable5.0.3≥5.1.5^5.1.5
flatted3.2.7≥3.4.0^3.4.0
ajv6.12.6 / 7.2.4≥6.14.0 / ≥8.18.0^8.18.0
dompurify3.2.0≥3.3.2^3.3.2
qs6.11.0≥6.14.2^6.14.2
@tootallnate/once2.0.0≥3.0.1^3.0.1

步骤 5: 添加 overrides 到 package.json

{
  "name": "your-project",
  "version": "1.0.0",
  "dependencies": {
    // 保持原有依赖不变
  },
  "devDependencies": {
    // 保持原有依赖不变
  },
  "pnpm": {
    "overrides": {
      "lodash": "^4.17.23",
      "minimatch": "^9.0.7",
      "rollup": "^4.59.0",
      "immutable": "^5.1.5",
      "flatted": "^3.4.0",
      "ajv": "^8.18.0",
      "dompurify": "^3.3.2",
      "qs": "^6.14.2",
      "@tootallnate/once": "^3.0.1"
    }
  }
}

步骤 6: 重新安装依赖

# 删除现有依赖(推荐)
rm -rf node_modules pnpm-lock.yaml

# 重新安装
pnpm install

步骤 7: 验证修复结果

# 1. 再次执行安全审计
npm audit --registry=https://registry.npmjs.org/

# 2. 检查特定包的版本
pnpm list lodash minimatch rollup

# 3. 运行项目测试
pnpm test

# 4. 启动项目验证功能
pnpm dev

步骤 8: 提交代码

git add package.json pnpm-lock.yaml .npmrc
git commit -m "fix: 修复 14 个安全漏洞 (9 High, 3 Moderate, 2 Low)"

常见问题

Q1: overrides 后仍有部分漏洞怎么办?

可能原因

  1. 某些包的版本范围冲突
  2. 上游依赖未更新
  3. overrides 配置不正确

解决方法

# 查看具体依赖路径
pnpm why <package-name>

# 使用更精确的 overrides
{
  "pnpm": {
    "overrides": {
      "minimatch@<3": "^3.1.4",
      "minimatch@>=9": "^9.0.7"
    }
  }
}

Q2: ajv 版本升级导致兼容性问题

问题: ajv v8 与 v6/v7 API 不兼容

解决方法

# 检查 ajv 使用情况
pnpm why ajv

# 如果有多个版本共存,分别指定
{
  "pnpm": {
    "overrides": {
      "ajv@6": "^6.14.0",
      "ajv@>=7": "^8.18.0"
    }
  }
}

Q3: npm audit 显示漏洞但 pnpm list 显示正确版本

原因: npm 和 pnpm 的依赖解析机制不同

解决方法

# 清除 npm 缓存
npm cache clean --force

# 使用 pnpm 原生审计(需配置 audit-registry)
pnpm audit

# 或使用第三方工具
npx snyk test

Q4: 只修复生产环境漏洞

如果开发依赖的漏洞可以接受:

# 仅审计生产依赖
npm audit --production

# 在 overrides 中只修复生产依赖的包

Q5: 修复后项目无法启动

回滚步骤

# 恢复备份
cp package.json.backup package.json
cp pnpm-lock.yaml.backup pnpm-lock.yaml

# 重新安装
pnpm install

# 逐个测试 overrides

最佳实践

1. 定期安全审计

package.json 中添加脚本:

{
  "scripts": {
    "audit": "npm audit --registry=https://registry.npmjs.org/",
    "audit:fix": "npm audit fix && pnpm install",
    "audit:prod": "npm audit --production --registry=https://registry.npmjs.org/"
  }
}

2. CI/CD 集成

在 GitHub Actions 中添加安全检查:

# .github/workflows/security-audit.yml
name: Security Audit

on:
  push:
    branches: [main, develop]
  pull_request:
  schedule:
    - cron: '0 0 * * 1'  # 每周一执行

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      
      - name: Setup pnpm
        uses: pnpm/action-setup@v2
        with:
          version: 8
      
      - name: Security Audit
        run: npm audit --audit-level=high --registry=https://registry.npmjs.org/
        continue-on-error: true
      
      - name: Generate Audit Report
        if: failure()
        run: npm audit --json > audit-report.json
      
      - name: Upload Audit Report
        if: failure()
        uses: actions/upload-artifact@v3
        with:
          name: security-audit-report
          path: audit-report.json

3. 使用 .npmrc 统一配置

# .npmrc
# 主注册源(国内镜像加速)
registry=https://registry.npmmirror.com/

# 安全审计使用官方源
audit-registry=https://registry.npmjs.org/

# 二进制文件镜像
sharp_binary_host=https://npmmirror.com/mirrors/sharp
electron_mirror=https://npmmirror.com/mirrors/electron/
puppeteer_download_host=https://npmmirror.com/mirrors
chromedriver_cdnurl=https://npmmirror.com/mirrors/chromedriver

# PNPM 配置
shamefully-hoist=false
strict-peer-dependencies=false

4. 自动化修复脚本

创建 scripts/fix-security.sh

#!/bin/bash

set -e

echo "🔍 Starting security vulnerability fix..."

# 1. 备份
echo "📦 Backing up package.json..."
cp package.json package.json.backup.$(date +%Y%m%d_%H%M%S)

# 2. 审计
echo "🔎 Running security audit..."
npm audit --registry=https://registry.npmjs.org/ || true

# 3. 自动修复(保守策略)
echo "🔧 Attempting auto-fix..."
npm audit fix --package-lock-only || true

# 4. 重新安装
echo "📥 Reinstalling dependencies..."
rm -rf node_modules pnpm-lock.yaml
pnpm install

# 5. 验证
echo "✅ Verifying fix..."
npm audit --registry=https://registry.npmjs.org/ || true

# 6. 生成报告
echo "📊 Generating report..."
npm audit --json --registry=https://registry.npmjs.org/ > audit-report.json 2>&1 || true

echo "✨ Done! Check audit-report.json for details."

5. 依赖更新策略

{
  "scripts": {
    "deps:check": "pnpm outdated",
    "deps:update": "pnpm update --latest",
    "deps:interactive": "pnpm update --interactive --latest"
  }
}

6. 使用 Dependabot 自动更新

创建 .github/dependabot.yml

version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 10
    reviewers:
      - "your-team"
    labels:
      - "dependencies"
      - "security"
    # 仅更新安全漏洞
    versioning-strategy: increase-if-necessary

工具推荐

安全审计工具对比

工具特点使用场景
npm audit官方工具,数据最准确日常审计
pnpm audit需要正确配置源PNPM 项目
yarn auditYarn 专用Yarn 项目
snyk功能强大,支持修复建议深度分析
OWASP dependency-check支持多语言,生成详细报告企业级安全扫描
npm-check-updates检查过期依赖依赖更新

使用 Snyk 进行深度分析

# 安装
npm install -g snyk

# 认证
snyk auth

# 测试
snyk test

# 自动修复
snyk fix

# 监控
snyk monitor

总结

核心要点

  1. 使用正确的审计源: 淘宝镜像不支持 audit,需配置官方源
  2. 使用 overrides 强制更新: 间接依赖无法直接更新
  3. 分步验证: 每次修复后都要测试功能
  4. 关注开发/生产分离: 开发依赖漏洞影响较小
  5. 自动化: CI/CD 集成,定期检查

修复效果

修复前:

14 vulnerabilities found
Severity: 2 low | 3 moderate | 9 high

修复后:

0 vulnerabilities found

维护建议


参考资料


文档版本: v1.0.0
最后更新: 2024-01-XX
作者: [Your Name]
许可: MIT


Suggest Changes

Previous Post
检查项目依赖的开源许可证
Next Post
使用 Flex 布局在不固定高度下实现可滚动列表的技巧