跳到主要内容

依赖安全扫描与供应链安全

1. 威胁模型

前端项目 90% 代码是依赖。供应链攻击:

  • typosquattingreactt lodahs 等假包
  • 依赖投毒:合法包被劫持发恶意版本(event-stream、ua-parser-js 历史事件)
  • 传递依赖:你装 1 个包,背后 200 个间接依赖
  • CVE 漏洞:lodash <4.17.21 prototype pollution
  • 生命周期脚本postinstall 任意执行代码

2. npm audit

npm audit
npm audit --audit-level=high
npm audit fix # 自动升级修复
npm audit fix --force # 含 breaking change(慎用)

audit-levelinfo | low | moderate | high | critical,只报指定及以上。

CI 集成:

- run: npm audit --audit-level=high

发现高危依赖 CI 失败。

3. 锁文件(lockfile)

package-lock.json / yarn.lock / pnpm-lock.yaml 锁定所有依赖(含传递)的精确版本 + integrity hash。

永远提交 lockfile 到 git

npm ci # 严格按 lockfile 安装(CI 用)
npm install # 可能改 lockfile(开发用)

npm ci vs npm install

  • ci:删除 node_modules 全装,不改 lockfile
  • install:增量装,可能改 lockfile

4. 第三方扫描工具

4.1 Snyk(最强)

npm i -g snyk
snyk auth
snyk test # 当前项目
snyk monitor # 持续监控
snyk container test myapp # 镜像扫描

GitHub App 集成自动 PR 修复。

4.2 Dependabot(GitHub 内置)

.github/dependabot.yml

version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
groups:
dev-deps:
dependency-type: "development"

自动开 PR 升级有漏洞 / 过时的依赖。

4.3 Renovate

更强大的依赖更新工具,可配置:

  • 自动 merge minor / patch
  • 限制时间窗
  • 分组更新
// renovate.json
{
"extends": ["config:base"],
"schedule": ["before 9am on Monday"],
"automerge": true,
"automergeType": "branch",
"packageRules": [
{
"matchUpdateTypes": ["minor", "patch"],
"automerge": true
},
{
"matchPackagePatterns": ["^@types/"],
"groupName": "type definitions"
}
]
}

4.4 OSV-Scanner(Google)

brew install osv-scanner
osv-scanner -L package-lock.json

5. 包来源验证

5.1 npm registry 配置

# 用官方 registry(默认)
npm config set registry https://registry.npmjs.org/

# 或私有 registry(公司)
npm config set registry https://registry.npmjs.example.com/

国内镜像:https://registry.npmmirror.com(淘宝),但生产构建建议官方源。

5.2 仅装签名包

npm v9+ 支持 --foreground-scripts 显示生命周期脚本。

npm install --ignore-scripts # 跳过 postinstall(最安全但很多包装不上)

6. 检测 typosquatting

提交前检查:

# 看新增依赖
git diff package.json | grep "\"[a-z]"

# 校验包真实性
npm view react versions
npm view react author
npm view react repository.url # 应指向 facebook/react

可疑包名:

  • 拼写错误(reactt、loadash)
  • 新发布且 download 极少
  • author 没历史包
  • 没 GitHub repo
  • README 抄袭知名包

7. SBOM(软件物料清单)

记录所有依赖供合规:

npm i -g @cyclonedx/cyclonedx-npm
cyclonedx-npm --output-file bom.json

存档每次发布的 SBOM,CVE 公布时能查影响范围。

8. 锁定 npm 行为

.npmrc

audit=true
fund=false
save-exact=true # 装包不带 ^ ~(精确版本)
package-lock=true
ignore-scripts=false # 视风险定
engine-strict=true # 严格 Node 版本检查

9. CI 安全集成

- name: Audit
run: npm audit --audit-level=high

- name: Snyk
uses: snyk/actions/node@master
env:
SNYK_TOKEN: $&#125;&#125; secrets.SNYK_TOKEN &#125;&#125;
with:
args: --severity-threshold=high

- name: SBOM
run: |
npx @cyclonedx/cyclonedx-npm --output-file bom.json

- uses: actions/upload-artifact@v4
with:
name: sbom
path: bom.json

10. 应急响应

某依赖被曝高危漏洞:

  1. npm ls &lt;pkg> 看是不是直接 / 传递依赖
  2. 看官方 advisory 影响版本
  3. 升级到 fixed version
  4. 不能升级时考虑:
    • 替换包
    • npm overrides 强制传递依赖版本:
    "overrides": {
    "vulnerable-pkg": "1.2.3"
    }
  5. 重新构建 + 部署所有环境

11. 常见反模式

  • lockfile 不提交:每次 install 拿不同版本
  • ^ ~ 范围依赖不锁:自动升小版本,可能引入漏洞
  • 不审 audit 输出:CI 即使报警也忽略
  • registry 用国内镜像装生产:镜像延迟可能拿到老版本,且镜像本身风险
  • 盲目 npm audit fix --force:引入 breaking change 把生产搞挂
  • 不验证新依赖:随手装个 cool-pkg 没看是谁发的
  • 生产装 dev 依赖:扩大攻击面(用 npm ci --omit=dev
  • postinstall 不审查:包安装即 RCE
  • 私有 registry 凭证写代码:泄露

12. 延伸阅读