从限制性基线开始
一个有用的基线是 default-src 'self',再为每类资源列出明确来源。脚本使用每响应 nonce 或哈希;object-src 'none' 阻止插件内容;base-uri 'self' 防止 base 标签劫持;frame-ancestors 'none' 防止点击劫持。
res.set('Content-Security-Policy', [
"default-src 'self'",
`script-src 'self' 'nonce-${nonce}'`,
"object-src 'none'",
"base-uri 'self'",
"frame-ancestors 'none'",
].join('; '));
步骤
- 为每个响应生成加密随机 nonce,并传给模板渲染器。
- 设置 CSP 头,脚本仅允许 self 与当前 nonce;按需为图片等资源列出来源。
- 为所有服务端渲染的 script 标签添加 nonce。移除内联事件处理器和基于 eval 的代码,因为它们会被策略阻止。
- 用浏览器控制台和
curl -sI验证:合法资源加载,注入的无 nonce 脚本不执行,frame-ancestors阻止嵌入。
验证
- HTML 响应包含 CSP 头。
- 合法资源没有 CSP 违规。
- 注入的
<script>alert(1)</script>不执行。 frame-ancestors阻止测试页面嵌入。- 第三方来源被明确列出,而不是使用通配符。
上线方式
先在 Content-Security-Policy-Report-Only 模式收集违规报告,修复合法断点后再强制。报告端点不要记录敏感 URL 或令牌。新增 CDN、分析脚本或字体提供商时重新审查策略。unsafe-inline 放在 style-src 会削弱保护,应逐步迁移到 nonce 或哈希。