You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 16:32:50