
依赖安全与供应链
NPM安全审计
# 检查漏洞
npm audit
npm audit --audit-level=high # 仅在高/严重级别时失败
# 自动修复(如可能)
npm audit fix
# 详细JSON报告
npm audit --json > audit-report.json
# 检查过时的包
npm outdated
# 使用socket.dev进行深度分析
npx socket npm install lodash

锁文件最佳实践
# 始终提交锁文件
git add package-lock.json # 或 yarn.lock / pnpm-lock.yaml
# 在CI中使用 --frozen-lockfile
npm ci # 严格遵循 package-lock.json
yarn install --frozen-lockfile
pnpm install --frozen-lockfile
# 验证锁文件完整性
npm ci --audit
依赖固定版本
{
"dependencies": {
"express": "4.18.2", // 固定版本 - 好
"lodash": "^4.17.21", // ^ 允许次要/补丁版本 - 可接受
"react": "~18.2.0", // ~ 仅允许补丁版本 - 可接受
"some-pkg": "*" // 通配符 - 危险
}
}

GitHub Actions安全扫描
# .github/workflows/security.yml
name: Security Scan
on: [push, pull_request]
jobs:
dependency-audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: NPM Audit
run: npm audit --audit-level=high
- name: Snyk vulnerability scan
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high
- name: OWASP Dependency Check
uses: dependency-check/Dependency-Check_Action@main
with:
project: 'myapp'
path: '.'
format: 'HTML'
args: --failOnCVSS 7
secret-scanning:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # 完整历史用于秘密扫描
- name: Gitleaks scan
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
sast:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
languages: javascript, typescript
SBOM(软件物料清单)
# 使用CycloneDX生成SBOM
npm install -g @cyclonedx/cyclonedx-npm
cyclonedx-npm --output-file sbom.json
# 使用Syft生成SBOM
syft packages . --output spdx-json=sbom.spdx.json
# 扫描SBOM与漏洞数据库对比
grype sbom:./sbom.json
# 将SBOM存储在CI工件中

私有包仓库
# 使用Verdaccio作为私有npm仓库
npm install -g verdaccio
verdaccio
# 配置npm使用私有仓库
npm set registry http://localhost:4873/
# 项目的.npmrc
@mycompany:registry=https://npm.company.com
//npm.company.com/:_authToken=${NPM_TOKEN}
# 阻止同名的公共包(命名空间抢注预防)
# package.json
{
"name": "@mycompany/internal-lib", // 作用域包
"private": true
}
预提交秘密检测
# 安装pre-commit
pip install pre-commit
# .pre-commit-config.yaml
repos:
- repo: https://github.com/Yelp/detect-secrets
rev: v1.4.0
hooks:
- id: detect-secrets
args: ['--baseline', '.secrets.baseline']
- repo: https://github.com/zricethezav/gitleaks
rev: v8.18.0
hooks:
- id: gitleaks
# 初始化
pre-commit install
pre-commit run --all-files
域名抢注检测
import requests
from difflib import SequenceMatcher
def check_typosquatting(package_name: str, threshold: float = 0.85) -> list:
"""检查包名是否与流行包名相似到可疑程度。"""
popular_packages = [
"express", "react", "lodash", "axios", "moment",
"webpack", "babel", "eslint", "prettier", "typescript"
]
suspicious = []
for popular in popular_packages:
similarity = SequenceMatcher(None, package_name, popular).ratio()
if similarity > threshold and package_name != popular:
suspicious.append({
"package": package_name,
"similar_to": popular,
"similarity": similarity,
})
return suspicious
# 安装前检查
result = check_typosquatting("expres") # 缺少's'
if result:
print(f"警告:可能的域名抢注:{result}")
安全策略
# .github/SECURITY.md 模板要点:
# - 支持的版本表格
# - 漏洞报告流程
# - 响应时间线(24小时确认,7天修复)
# Dependabot自动更新
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
reviewers:
- "security-team"
labels:
- "security"
open-pull-requests-limit: 10