解释在 grunt 中实现漏洞修复 MR 自动创建
解读
面试官问的是“如何用 Grunt 把漏洞修复这件事做成自动化 Merge Request”。
国内主流代码托管是 GitLab(私有部署版),所以考点是:
- 让 Grunt 感知漏洞(依赖库 CVE、SAST 扫描结果);
- 自动改代码(升级版本号、打补丁);
- 调用 GitLab API 创建 MR;
- 把整条链路串成一条 Grunt 任务,CI 里一键触发。
回答时要体现**“老工具新玩法”**:Grunt 只做编排,真正干活的是插件+脚本,但入口必须是 grunt 命令,否则跑题。
知识点
- grunt-contrib-watch:监听
npm audit、pnpm audit或snyk test生成的 json 报告,报告变化即触发后续任务。 - grunt-exec:在 Gruntfile 里跑 shell,例如
npm audit fix --package-lock-only --dry-run先试修,确认无 break change 再真修。 - grunt-bump:把
package.json版本号按公司规范(语义化+内部日历版本)自动 +1,并写回文件。 - grunt-git:
git add package*.json && git commit -m "security: fix CVE-2024-xxxx",同时新建分支security-patch-${timestamp}。 - node-gitlab 或原生 fetch:用 GitLab Personal Access Token(国内习惯叫私有令牌)调
POST /projects/:id/merge_requests,指定source_branch、target_branch(通常是 release)、title、description(贴上 audit 报告截图地址与漏洞列表)。 - MR 模板:在
.gitlab/merge_request_templates/security.md预置检查项,Grunt 调用 API 时把template=security带进去,保证评审人一眼看到影响面。 - 失败回滚:Grunt task 链里加
grunt.fail.fatal,如果单元测试(grunt-contrib-jasmine/grunt-karma)未通过,则自动git branch -D本地临时分支并退出 CI,防止污染。 - 钉钉/飞书机器人:
grunt-http把 MR 地址推给安全群,@ 对应责任人,符合国内“安全事件 30 分钟内响应”的合规要求。
答案
-
在项目根目录装依赖
npm i -D grunt grunt-contrib-watch grunt-exec grunt-bump grunt-git node-gitlab @types/node -
新建
grunt/security-patch.js,封装 GitLab 客户端:const { Gitlab } = require('gitlab'); const api = new Gitlab({ token: process.env.GITLAB_TOKEN, host: 'https://git.company.cn' }); exports.createMR = async (projId, branch, title, desc) => { return api.MergeRequests.create(projId, branch, 'release', title, { description: desc }); }; -
Gruntfile.js核心任务链:module.exports = function(grunt) { grunt.initConfig({ exec: { audit: 'npm audit --json > audit.json', fix: 'npm audit fix --package-lock-only' }, bump: { options: { files: ['package.json'], commit: false, createTag: false, push: false } }, gitadd: { task: { files: { src: ['package.json', 'package-lock.json'] } } }, gitcommit: { task: { options: { message: 'security: auto fix CVEs' } } }, gitbranch: { task: { options: { name: 'auto/<%= grunt.template.today("yyyymmddHHMM") %>' } } } }); grunt.registerTask('createMR', async function() { const done = this.async(); const { createMR } = require('./grunt/security-patch'); const projId = process.env.CI_PROJECT_ID || '123'; const branch = grunt.config.get('gitbranch.task.options.name'); const mr = await createMR(projId, branch, `【安全】自动修复高危漏洞 ${grunt.template.today('yyyy-mm-dd')}`, '详见 CI 报告附件,已跑通单元测试'); grunt.log.oklns('MR 地址:' + mr.web_url); done(); }); grunt.registerTask('security', ['exec:audit', 'exec:fix', 'bump:patch', 'gitbranch', 'gitadd', 'gitcommit', 'createMR']); }; -
.gitlab-ci.yml里加一条:security: stage: check only: - schedules # 每周一凌晨跑 script: - npm run grunt security -
效果:
周一 02:00 CI 自动检出漏洞 → 本地修复 → 版本号 +0.0.1 → 推新分支 → 创建 MR → 钉钉群收到卡片 → 安全工程师上班直接评审合并,全程零人工。
拓展思考
- 多仓库批量修复:把 Gruntfile 做成独立脚手架包
@company/grunt-security,通过grunt-hub一次性扫描上百个前端仓库,实现“集团级漏洞治理”。 - 与 SCA 平台对接:国内银行常用 奇安信、悬镜 等 SCA,Grunt 任务里解析它们导出的 csv,把 CVE 与组件坐标映射成
npm|axios@0.21.1格式,再精准升级,避免“一刀切”带来的回归问题。 - MR 质量门禁:在 GitLab 私有版里启用 Approval Rule,要求“安全团队 + 测试团队”双签;Grunt 调用 API 时直接把
approval_rules参数写进去,防止开发私自合并。 - 灰度发布:Grunt 任务链再加一步
grunt-ssh,把修复后的包推到 内部 Verdaccio 私服 的beta频道,让低流量业务先验证 24h,无告警再正式发版,实现“安全修复也能灰度”。