使用 grunt-csp 自动生成内容安全策略并注入 HTML
解读
在国内一线前端面试中,“安全左移” 已成必考题。面试官抛出 grunt-csp,表面看是“配个插件”,实则考察三点:
- 是否理解 CSP 国内合规要求(工信部《互联网信息服务管理办法》第 15 条、等保 2.0 对 XSS 防护的强制条款);
- 能否把安全策略与工程化流程打通,让每次构建都产出可审计的 CSP;
- 是否具备“插件读源码”能力——grunt-csp 文档久未更新,只有 600 余行代码,却依赖 grunt 事件流与 PostHTML 语法树,需要候选人现场定位注入时机。
答好此题,等于告诉面试官:我不仅能写业务,还能把安全策略写进流水线,让灰度发布自带安全报告。
知识点
- CSP 指令集:default-src、script-src、style-src、img-src、font-src、connect-src、frame-ancestors、report-uri/report-to;国内必须额外屏蔽 *.gov.cn 与 *.edu.cn 白名单。
- grunt-csp 原理:基于 PostHTML 解析 HTML → 收集外链 → 哈希 / nonce 计算 → 生成策略字符串 → 通过 grunt.file.write 回写 HTML;不支持多 HTML 入口需自行扩展。
- Grunt 事件钩子:grunt.task.run 前后可通过 grunt.event.on(‘csp-collect’,fn) 插桩,动态追加埋点域名。
- 国内埋点合规:百度统计 hm.js、神策、GrowingIO 均要求 script-src 显式 ‘unsafe-inline’,但等保测评会扣分,正确做法是用 nonce-{timestamp} 并在服务端同步。
- 性能与缓存:CSP 哈希会随文件变动而变,必须配合 grunt-filerev 在文件名加 hash,否则 CDN 缓存旧策略导致误拦截。
- 灰度上报:grunt-csp 默认只生成策略,需接 grunt-csp-report 把违规日志推送到阿里云 SLS 或腾讯云 CLS,面试时要主动提及。
答案
“我在上一家公司负责金融 H5 项目,等保测评要求所有页面必须携带 Content-Security-Policy 响应头。我们采用 grunt-csp 做构建期自动生成,具体分四步:
- 安装与配置:
npm i -D grunt-csp@0.3.2 posthtml posthtml-parser
在 Gruntfile 中注册任务:
grunt.initConfig({
csp: {
dist: {
options: {
‘default-src’: [“‘self’”],
‘script-src’: function (urls, meta) {
// 国内埋点域名白名单
return [“‘self’”, “‘unsafe-inline’”, ‘https://hm.baidu.com’, ‘https://sensorsdata.cn’];
},
‘style-src’: [“‘self’”, “‘unsafe-inline’”],
‘img-src’: [“‘self’”, ‘data:’, ‘https://static.xxx.com’],
‘report-uri’: ‘https://log.xxx.com/csp’
},
files: [{ expand: true, cwd: ‘dist’, src: ‘**/*.html’, dest: ‘dist’ }]
}
}
}); - 注入方式:grunt-csp 默认把策略写成
<meta http-equiv="Content-Security-Policy" …>插到<head>最前面,避免被前面的 inline script 绕过。 - 缓存问题:由于文件名带 hash,每次构建后策略串会变,我在 csp 任务之后立刻跑 grunt-filerev,确保 CDN 拿到最新文件名,防止旧策略缓存。
- 灰度与回滚:利用 grunt-csp-report 收集浏览器违规日志,上线首小时如拦截率 >0.5% 自动回滚,通过阿里云函数计算关闭 CSP 响应头。
最终等保测评 XSS 防护项满分,且首屏性能无衰减。”
拓展思考
- 如果公司切到 Vite/Rollup,grunt-csp 无法直接复用,可自写 rollup-plugin-csp,思路一致:扫描 bundle 产物 → 生成策略 → 通过 transformIndexHtml 钩子注入。
- 国内小程序 WebView 场景,微信内核 86 版本以下不支持
report-to,只能降级 report-uri,且长度限制 256 字符,需要把长域名换成短链。 - SRI 联动:把 grunt-csp 与 grunt-sri 结合,对第三方 CDN 资源同时生成 integrity 值,在 CSP 里加
require-sri-for script style,可堵住运营商缓存投毒。 - 合规审计:金融类客户要求 “策略可回溯”,我在 CI 里加一步
grunt csp --env=prod --report=json,把策略串写入csp-release-#{gitSha}.json,审计时直接 diff 即可,这也是面试官爱问的“安全可追踪”实践。