症状
控制台违规信息就是完整的事故报告:被拒的脚本 URL 加触发的指令 “script-src ‘self’”——规则与资源不合就是全部 bug。同类违规对其他资源类型形态一致:connect-src 拦 XHR、style-src 拦内联样式、img-src 拦打点像素。把它们读成一张”(指令, 源)“清单,策略要么显式放行、要么交付侧迁移。内联事件处理器与基于 eval 的库在新策略下停摆,是 style/script 指令收紧的连带后果。
诊断思路
先按 CSP 过滤控制台读出每条违规的指令与被拦 URL;再检查有效响应头——多个 CSP 头会取交集(最严者胜),单一多指令策略远比多个竞争头好推理;最后用 Report-Only 头做干跑:只上报不拦截,先收齐完整违规集再谈强制。
根因
CSP 由浏览器按资源类型执行源白名单。任何落在指令白名单之外的资源——脚本、样式、连接、图片、字体——在加载时被拒。策略与页面实际的交付图对“哪些源合法”意见不一致。
修复与验证
Report-Only 收集违规,把真实使用的源逐指令补进白名单;内联脚本用 nonce 或 hash 取代 unsafe-inline;报告流干净后再切换强制。nonce 每响应生成一次、随响应下发、内联脚本标记之——保住内联能力而不开全局后门。验证时强制模式下控制台零违规、完整用户旅程功能正常、报告端点不再收到新报告。为一个报错就加 unsafe-inline 或通配域等于永久削弱策略——用 nonce 与精确源。
代码示例
Refused to load the script from
'https://cdn.partner.example.com/widget.js'
because it violates the following Content Security Policy
directive: "script-src 'self'"
Content-Security-Policy-Report-Only:
default-src 'self';
script-src 'self' 'nonce-r4nd0m' https://cdn.partner.example.com;
connect-src 'self' https://api.example.com;
style-src 'self' 'nonce-r4nd0m';
report-uri /csp-report;
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-r4nd0m' https://cdn.partner.example.com 'strict-dynamic';
report-uri /csp-report;