如何用npm audit结果为合并请求添加阈值以上漏洞依赖注释?
实现合并请求中添加npm audit风险依赖注释的方案
核心思路是:导出npm audit的结构化结果,筛选出符合风险阈值的漏洞,再通过CI平台的API将结果添加为合并请求注释。以下是主流CI平台的具体实现:
GitHub Actions 实现步骤
1. 配置工作流文件(.github/workflows/npm-audit-comment.yml)
name: NPM Audit PR Comment on: pull_request: types: [opened, synchronize] jobs: audit-comment: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 20 cache: 'npm' - name: Install dependencies run: npm ci - name: Run npm audit and export results run: npm audit --json > audit-results.json - name: Generate PR comment content id: generate-comment run: node ./scripts/process-audit-results.js env: SEVERITY_THRESHOLD: 'high' # 可自定义:low/moderate/high/critical - name: Add comment to PR uses: actions/github-script@v7 if: steps.generate-comment.outputs.comment_content != '' with: script: | github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: `${{ steps.generate-comment.outputs.comment_content }}` })
2. 编写结果处理脚本(scripts/process-audit-results.js)
const fs = require('fs'); const { SEVERITY_THRESHOLD } = process.env; // 定义风险等级优先级,用于筛选 const severityLevels = { low: 1, moderate: 2, high: 3, critical: 4 }; const thresholdLevel = severityLevels[SEVERITY_THRESHOLD.toLowerCase()]; if (!thresholdLevel) { console.error('无效的风险阈值,请设置为 low/moderate/high/critical'); process.exit(1); } // 读取audit结果 const auditResults = JSON.parse(fs.readFileSync('./audit-results.json', 'utf8')); const vulnerabilities = auditResults.vulnerabilities || {}; // 筛选出超过阈值的漏洞 const filteredVulns = Object.values(vulnerabilities).filter(vuln => { return severityLevels[vuln.severity.toLowerCase()] >= thresholdLevel; }); if (filteredVulns.length === 0) { console.log('::set-output name=comment_content::'); process.exit(0); } // 生成Markdown格式的注释内容 let commentBody = `### 🚨 检测到高风险依赖漏洞\n\n`; commentBody += `风险阈值:${SEVERITY_THRESHOLD.toUpperCase()}\n\n`; commentBody += `| 依赖库 | 风险等级 | 漏洞ID | 影响版本 | 修复方案 |\n`; commentBody += `|--------|----------|--------|----------|----------|\n`; filteredVulns.forEach(vuln => { const fixVersion = vuln.fix?.versions || '暂无修复版本'; commentBody += `| ${vuln.name} | **${vuln.severity.toUpperCase()}** | ${vuln.cwe?.join(', ') || '无'} | ${vuln.range} | ${fixVersion} |\n`; }); console.log(`::set-output name=comment_content::${commentBody}`);
GitLab CI 实现步骤
1. 配置.gitlab-ci.yml
npm-audit-comment: stage: test image: node:20-alpine only: - merge_requests variables: SEVERITY_THRESHOLD: "high" # 自定义风险阈值 GITLAB_API_TOKEN: $CI_JOB_TOKEN # 使用内置的Job Token,需确保项目权限允许 script: - npm ci - npm audit --json > audit-results.json - node ./scripts/process-audit-results.js > comment-content.txt - | if [ -s comment-content.txt ]; then curl --request POST \ --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" \ --header "Content-Type: application/json" \ --data "{\"body\": \"$(cat comment-content.txt)\"}" \ "$CI_API_V4_URL/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID/notes" fi
2. 结果处理脚本(scripts/process-audit-results.js)
和GitHub Actions版本类似,输出改为直接打印注释内容:
const fs = require('fs'); const { SEVERITY_THRESHOLD } = process.env; const severityLevels = { low: 1, moderate: 2, high: 3, critical: 4 }; const thresholdLevel = severityLevels[SEVERITY_THRESHOLD.toLowerCase()]; if (!thresholdLevel) { console.error('无效的风险阈值,请设置为 low/moderate/high/critical'); process.exit(1); } const auditResults = JSON.parse(fs.readFileSync('./audit-results.json', 'utf8')); const vulnerabilities = auditResults.vulnerabilities || {}; const filteredVulns = Object.values(vulnerabilities).filter(vuln => { return severityLevels[vuln.severity.toLowerCase()] >= thresholdLevel; }); if (filteredVulns.length === 0) { process.exit(0); } let commentBody = `### 🚨 检测到高风险依赖漏洞\n\n`; commentBody += `风险阈值:${SEVERITY_THRESHOLD.toUpperCase()}\n\n`; commentBody += `| 依赖库 | 风险等级 | 漏洞ID | 影响版本 | 修复方案 |\n`; commentBody += `|--------|----------|--------|----------|----------|\n`; filteredVulns.forEach(vuln => { const fixVersion = vuln.fix?.versions || '暂无修复版本'; commentBody += `| ${vuln.name} | **${vuln.severity.toUpperCase()}** | ${vuln.cwe?.join(', ') || '无'} | ${vuln.range} | ${fixVersion} |\n`; }); console.log(commentBody);
关键注意事项
- 权限配置:GitHub Actions中
GITHUB_TOKEN默认已有PR评论权限;GitLab需确保CI_JOB_TOKEN拥有api权限(在项目设置→CI/CD→流水线权限中开启)。 - 阈值自定义:通过环境变量
SEVERITY_THRESHOLD可调整风险等级,比如设为critical只显示最高风险漏洞。 - 重复注释处理:如果需要避免每次PR推送都重复添加注释,可以在脚本中先查询已有的评论,判断是否已存在相同内容再决定是否添加。
内容的提问来源于stack exchange,提问作者Rémi
相关产品推荐
相关产品推荐

