Skip to content
On this page

npm 安全最佳实践

npm安全是现代JavaScript开发中的重要考虑因素。本章将详细介绍如何保护您的npm项目免受安全威胁,包括依赖审计、权限管理、安全配置等方面。

安全威胁类型

恶意包威胁

npm生态系统中可能存在恶意包,常见的威胁包括:

  • 数据窃取:收集敏感信息
  • 供应链攻击:通过依赖链传播恶意代码
  • 挖矿脚本:利用系统资源
  • 键盘记录:捕获用户输入

依赖漏洞

  • 已知漏洞:包含CVE报告的安全漏洞
  • 过时依赖:使用有漏洞的旧版本
  • 间接依赖:依赖链中的脆弱包

npm内置安全功能

npm audit

npm内置安全审计功能:

bash
# 检查项目中的安全漏洞
npm audit

# 详细报告
npm audit --audit-level high

# JSON格式输出
npm audit --json

# 仅检查生产依赖
npm audit --production

# 仅检查开发依赖
npm audit --dev

自动修复

bash
# 自动修复兼容的漏洞
npm audit fix

# 安装可能破坏兼容性的修复
npm audit fix --force

# 仅修复特定严重级别的漏洞
npm audit fix --audit-level=moderate
npm audit fix --audit-level=high
npm audit fix --audit-level=critical

# 检查修复结果
npm audit

安全配置

bash
# 配置安全相关设置
npm config set audit true        # 启用自动审计
npm config set audit-level low   # 设置最低审计级别
npm config set fund false        # 禁用funding消息

# 查看安全配置
npm config list | grep audit

依赖安全管理

依赖审查

bash
# 检查所有依赖
npm ls --depth=0

# 检查特定依赖
npm ls package-name

# 检查依赖树
npm ls --depth=Infinity

# 检查过时的包
npm outdated

依赖最小化

json
{
  "scripts": {
    "check-deps": "npx depcheck",
    "unused-deps": "npx npm-check --skip-unused false"
  }
}

依赖验证

bash
# 验证包的完整性
npm view package-name --json

# 检查包的发布历史
npm view package-name time

# 检查包的维护者
npm owner ls package-name

包发布安全

账户安全

两因素认证 (2FA)

bash
# 为npm账户启用2FA
npm profile enable-2fa auth-and-writes

# 检查2FA状态
npm profile get 2fa

访问令牌

bash
# 创建访问令牌
npm token create --read-only
npm token create --cidr=192.168.0.1/24  # 限制IP范围

# 列出令牌
npm token list

# 删除令牌
npm token revoke <token>

发布前检查

bash
# 检查将要发布的文件
npm pack --dry-run

# 验证package.json
npm run prepublishOnly

# 检查敏感信息
npx npm-check-updates --error-level 2

权限管理

全局包权限

bash
# 避免使用sudo安装包
# 正确做法:配置npm使用本地目录
mkdir ~/.npm-global
npm config set prefix '~/.npm-global'
export PATH=~/.npm-global/bin:$PATH

# 或使用nvm管理Node.js
nvm install --lts

工作目录权限

bash
# 确保项目目录权限正确
chmod 755 .
chmod 644 package.json
chmod 644 package-lock.json

依赖锁定

package-lock.json安全

bash
# 始终提交package-lock.json
git add package-lock.json

# 使用npm ci进行可重现构建
npm ci

# 验证锁文件完整性
npm audit
npm ls

内容安全策略

json
{
  "engines": {
    "node": ">=16.0.0",
    "npm": ">=8.0.0"
  },
  "scripts": {
    "preinstall": "node verify-dependencies.js",
    "postinstall": "npm audit --audit-level moderate"
  }
}

代码安全扫描

静态代码分析

json
{
  "scripts": {
    "security:scan": "snyk test",
    "security:auth": "snyk auth $SNYK_TOKEN",
    "security:monitor": "snyk monitor"
  }
}

漏洞扫描工具

bash
# 使用Snyk扫描
npm install -g @snyk/cli
snyk test
snyk monitor

# 使用Retire.js扫描过时依赖
npm install -g retire
retire

# 使用Osano Cookie Scanner
npx @osano/cookie-scanner

安全配置

.npmrc安全配置

# .npmrc
# 禁用脚本执行(实验性功能)
ignore-scripts=true

# 设置审计级别
audit-level=moderate

# 禁用资金推广
fund=false

# 设置超时
fetch-timeout=60000

# 验证SSL
strict-ssl=true

package.json安全配置

json
{
  "name": "my-secure-project",
  "scripts": {
    "preinstall": "node scripts/check-engines.js",
    "postinstall": "npm audit --audit-level moderate",
    "security": "npm audit && snyk test"
  },
  "engines": {
    "node": ">=16.14.0",
    "npm": ">=8.0.0"
  },
  "engineStrict": true,
  "private": true
}

CI/CD安全

GitHub Actions安全

yaml
# .github/workflows/security.yml
name: Security Checks
on: [push, pull_request]

jobs:
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'npm'
          
      - name: Install dependencies
        run: npm ci
        env:
          CI: true
          
      - name: Run audit
        run: npm audit --audit-level moderate
        
      - name: Run Snyk
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

依赖更新自动化

yaml
# .github/workflows/dependabot.yml
name: Dependabot
on: pull_request

permissions:
  contents: write
  pull-requests: write

jobs:
  dependabot:
    runs-on: ubuntu-latest
    if: ${{ github.actor == 'dependabot[bot]' }}
    steps:
      - name: Dependabot metadata
        id: metadata
        uses: dependabot/fetch-metadata@v1.1.1
        with:
          github-token: "${{ secrets.GITHUB_TOKEN }}"
          
      - name: Enable auto-merge for Dependabot PRs
        if: ${{steps.metadata.outputs.update-type == 'version-update:semver-patch'}}
        run: gh pr merge --auto --merge "$PR_URL"
        env:
          PR_URL: ${{github.event.pull_request.html_url}}
          GH_TOKEN: ${{secrets.GITHUB_TOKEN}}

供应链安全

签名验证

bash
# 验证包签名(实验性功能)
npm config set sign-git-tag true

# 使用Provenance
# 在package.json中添加
{
  "publishConfig": {
    "provenance": true
  }
}

依赖来源验证

bash
# 检查包来源
npm view package-name --json | jq '.versions[].dist.tarball'

# 验证发布者
npm view package-name maintainers

安全监控

持续监控

json
{
  "scripts": {
    "security:watch": "nodemon --exec 'npm audit'",
    "security:daily": "npm audit --json | jq '.metadata.vulnerabilities'",
    "security:weekly": "npx npm-check-updates -u && npm audit"
  }
}

监控服务集成

bash
# 集成Snyk
snyk monitor --org=my-org --project-name=my-project

# 集成GitHub Security
gh extension install github/gh-sbom
gh sbom

应急响应

漏洞响应计划

json
{
  "scripts": {
    "security:response": "node scripts/security-response.js",
    "security:update": "npm update && npm audit",
    "security:rollback": "git reset --hard HEAD~1 && npm ci"
  }
}

恶意包处理

bash
# 如果发现恶意包
npm uninstall malicious-package

# 检查受影响的依赖
npm ls malicious-package

# 检查是否已执行恶意代码
find . -name "*.log" -exec grep -l "malicious" {} \;

安全工具推荐

依赖分析工具

bash
# depcheck - 检查未使用的依赖
npx depcheck

# bundlephobia - 检查包大小
npx bundlephobia-cli package-name

# npm-check - 检查过时和未使用的包
npx npm-check

# license check - 检查许可证合规性
npx license-checker --summary

安全扫描工具

bash
# npm audit - 内置安全审计
npm audit

# Snyk - 漏洞扫描
npm install -g @snyk/cli
snyk test

# Retire.js - 检测已知漏洞
npm install -g retire
retire

# Node Security Platform (停止维护,使用npm audit替代)
# npm install -g nsp
# nsp check

安全最佳实践清单

开发阶段

  • [ ] 使用npm audit定期检查漏洞
  • [ ] 启用自动审计 (npm config set audit true)
  • [ ] 验证第三方包的信誉
  • [ ] 最小化依赖数量
  • [ ] 使用固定版本或^版本号
  • [ ] 检查包的下载量和维护状态
  • [ ] 避免使用不维护的包

发布阶段

  • [ ] 启用2FA (npm profile enable-2fa)
  • [ ] 使用访问令牌而不是密码
  • [ ] 验证发布内容 (npm pack --dry-run)
  • [ ] 设置适当的引擎要求
  • [ ] 检查许可证合规性

运维阶段

  • [ ] 定期运行安全扫描
  • [ ] 监控依赖更新
  • [ ] 设置自动安全通知
  • [ ] 实施应急响应计划
  • [ ] 定期审查访问权限

通过遵循这些安全最佳实践,您可以显著提高npm项目的整体安全性,减少供应链攻击和其他安全威胁的风险。