“加了 CSP 还是被 XSS 打穿”是前端安全里常见的困惑。很多站点只写了 default-src 'self',却在页面里大量使用内联脚本;为了让它跑起来,又加回 'unsafe-inline',CSP 就只剩下一个响应头。
Content Security Policy 通过响应头告诉浏览器:哪些来源的脚本、样式、图片、字体、连接可以加载,哪些内联代码可以执行。它能显著降低 XSS 的影响,但不是 XSS 过滤器;服务端输出转义仍然要做。
举个常见例子:服务端把用户输入直接拼进 HTML,CSP 不会阻止这段 HTML 被解析;它只能在脚本执行时决定是否放行。输出编码和参数化查询仍然是第一道防线。
一个常见的严格配置:
Content-Security-Policy: default-src 'self'; script-src 'nonce-abc123' 'strict-dynamic'; object-src 'none'; base-uri 'none'default-src 'self' 限制默认来源;script-src 定义脚本来源;object-src 'none' 禁用插件;base-uri 'none' 防止 <base> 标签被注入后改写相对路径。script-src 还可以拆成 script-src-elem(外部脚本和 <script> 标签)和 script-src-attr(内联事件处理器),便于分别收紧。
frame-ancestors 控制哪些页面可以嵌入当前页面,能降低点击劫持风险;form-action 限制表单提交目标,防止注入的表单把数据发到外部。
nonce 是每次响应生成的随机值,服务端把它写进 CSP 头和页面里的 <script nonce="...">。两者一致,浏览器才执行这段内联脚本。
<script nonce="abc123">
console.log('allowed');
</script>关键点是“每次响应都不同”。如果 nonce 被缓存、被写死在静态 HTML 里,攻击者就能预测或复用,nonce 就失去意义。使用 CDN 或页面缓存时,要确保 CSP 头和 HTML 一起生成,不能缓存一份带 nonce 的页面发给所有人。
如果页面是静态生成的,无法为每个响应生成 nonce,可以用 hash:script-src 'sha256-...'。hash 适合固定内容的内联脚本,但脚本一改,hash 就要更新。
传统 CSP 用域名白名单,但现代前端往往从 CDN 动态加载脚本,白名单很难维护。'strict-dynamic' 的规则是:只要脚本由已受信任的脚本创建,就允许执行;主机白名单在支持 CSP3 的浏览器里会被忽略。
它适合配合 nonce 使用:入口脚本带 nonce,后续它加载的脚本自动获得信任。但这也意味着,一旦入口脚本被攻破,它加载的恶意脚本同样会被信任;strict-dynamic 不是“更安全”,而是把信任边界集中到了入口脚本。strict-dynamic 还需要配合 'nonce-...' 或 hash 使用;只写 'strict-dynamic' 没有信任根,等于没有放行任何脚本。
第一,nonce 和 'unsafe-inline' 同时存在。支持 CSP2 的浏览器会忽略 'unsafe-inline',但老浏览器可能仍然执行内联脚本;不要指望它做降级。
第二,内联事件处理器。onclick="..." 不受 nonce 保护,需要改成 addEventListener,或者用 'unsafe-hashes' 加 hash 放行,但后者会扩大攻击面。
第三,第三方脚本。分析、客服、广告脚本往往需要放宽 script-src;能放到独立 iframe 或单独页面的,尽量不要和主站共用策略。
第四,先用 Content-Security-Policy-Report-Only 观察。直接上强制策略容易把业务打挂;先收集报告,确认没有漏配,再切换。report-uri 和 report-to 可以收集违规报告;报告里可能带页面 URL 和拦截指令,接入日志系统时要注意脱敏。
报告阶段不要只看数量,要看被拦截的资源是不是业务必需;有些第三方脚本会动态插入内联代码,必须先改造成 nonce/hash 才能收紧。
Content-Security-Policy-Report-Only,收集被拦截的资源和页面;onclick 这类事件处理器;default-src、object-src、base-uri、frame-ancestors;CSP 的核心不是“写一个头”,而是把脚本来源收窄到可解释的范围。nonce 负责内联脚本,strict-dynamic 负责动态加载,report-only 负责灰度。三者配合,才能在不影响业务的前提下降低 XSS 风险。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。