content-security-policy-report-only 实测:30 个首页只有 1 家先预览再强制
content-security-policy-report-only 让浏览器只报告不拦截,是上线强制策略前最安全的一步。2026-10-07 单次抓取 30 个首页:19 家发了 Content-Security-Policy,只有 1 家先发 report-only。

实测 · 2026-10-07 · 30 个首页 · 每站一次 HTTP 请求 · 只读响应头
样本与口径:沿用 2026-08-15 起的固定 34 域面板,2026-10-07 用桌面 UA 各抓一次、不做渲染。只读响应头。canva.com / stackoverflow.com / medium.com / nytimes.com 返回 403,剔除;其余 30 个首页返回 200。
content-security-policy-report-only 让浏览器按策略判断、把「本来会被拦掉的东西」记下来,但一个资源都不真拦。它是上线一条强制策略前最安全的一步。2026-10-07 单次抓取这 30 个首页:19 家发了 Content-Security-Policy,只有 1 家先发 report-only。
怎么测的
每个域名一次 GET,不重试、不跑 JS。这个面板是开发者向站点加新闻站加我们自己 4 个站的便利样本,不是全网随机抽样,所以所有数字只读成「这 30 个里」,不要读成全网。我们记了一组固定的安全与缓存响应头,凡是发现策略的,再记下值里出现了哪些指令名。
| 响应头 | 首页数 | 作用 |
|---|---|---|
Content-Security-Policy | 19 | 强制策略,命中即拦截 |
Content-Security-Policy-Report-Only | 1 | 只报告,不拦截 |
X-Frame-Options | 17 | 禁止被别的站嵌进框架 |
| 两种防嵌套头都没有 | 9 | 任何站都能把它嵌进去 |
面板上唯一发预览头的站是 webflow.com。其余发了策略的站,都是一步直接上强制。还有 4 个站压根没发策略——就是我们自己运营的那四个。
这些策略其实很宽
19 条强制策略并不紧。其中 15 条带了 unsafe-inline,等于不管上面的来源清单怎么写,页面自己的内联脚本都放行;9 条带了 unsafe-eval,同理放行字符串转代码。这两个关键字是策略「看起来严、实际松」最常见的口子,也正是 report-only 预览本该提前照出来的东西。
| 指令 | 19 条策略里出现 |
|---|---|
style-src | 15 |
unsafe-inline | 15 |
script-src | 14 |
default-src | 13 |
frame-ancestors | 13 |
unsafe-eval | 9 |
object-src | 7 |
base-uri | 6 |
report-uri | 3 |
nonce- 源 | 2 |
指令覆盖也不齐:19 条里 15 条写了 style-src,14 条写了 script-src,13 条给了 default-src 兜底、13 条写了 frame-ancestors。只有 7 条写 object-src——规范把它当成脚本策略的必备搭档;6 条写 base-uri。真正声明 report-uri、也就是告诉浏览器「违规往哪儿报」的,只有 3 条;把 nonce- 源和其余策略配套写的,2 条。
防嵌套被拆在两个头里。把 X-Frame-Options 和 frame-ancestors 合起来算,30 个首页里 21 个至少用了一种方式挡住被嵌,9 个完全没挡——包括我们自己那 4 个站。这句话之所以写在这儿,就是因为它是我们自己测出来的。
为什么 content-security-policy-report-only 这一步总被跳过
report-only 用的是同一套策略语法,只差一件事:浏览器把违规「报告」出来,而不是拒绝加载。策略是真的,强制是关的。于是你能拿到一份清单——严格策略会打断哪些东西:一个内联事件处理、一个第三方字体、一段注入的样式——同时页面照常工作。这套行为在 CSP Level 3 规范里定义,MDN 的 Content-Security-Policy-Report-Only 词条按头逐项讲清了它(两处均 2026-10-07 访问)。
大多数团队的顺序是反的:先写好策略、直接上强制,再在生产环境里发现它把自家哪个资源切断了。这个面板上 15 条策略放行 unsafe-inline,而那个关键字往往就是第一次上强制打断东西之后补进去的,不是之前。预览这一步本来就是为了避免这件事,而面板上几乎没人做。
一条从没跑过 report-only 的策略,等于第一次在生产环境里执行它。
你可以照着做什么
预览这一步很短,而它恰恰是这个面板里几乎没人做的那一件事。把你真正想要的策略先当报告发出去,看一周,再把活下来的版本转成强制。
- 先把严格版放进
Content-Security-Policy-Report-Only,让它跑一周真实流量。 - 把
report-uri(或更新的report-to)指向你能收的端点,收集违规报告。没有落地端点,report-only 就是静默的,什么也告诉你不了。 - 看报告里哪些是断不得的资源,把它们有意识地加进来源,然后才把同一条策略搬到强制头上。
- 切换之后再抓一次头。上线过程里悄悄多出来的
unsafe-inline,已经不是你审过的那条策略了。
如果你干脆不跑策略,那是另一个决定——我们自己那 4 个站就属于这种,这也是这次测量能把它直说、而不用含糊的前提。防嵌套是更便宜的那一半:一行 frame-ancestors 就能补上点击劫持的口子,且完全不动你自己页面怎么加载。想把策略和你自家渲染的关系看全,手册那篇 content-security-policy 会不会挡住渲染器 逐条讲;unsafe-inline 的 27 个首页实测是本次的姐妹篇。头修对之后,再用我们的 AI 爬虫可达性检查看页面本身。
常见问题
content-security-policy-report-only 会拦东西吗?
不会,只报告、只放行。这就是它的全部用意,也是它能当上线第一步的原因。代价是:在你还停留在预览模式时,这条策略本来要降的风险一点没降。
能同时发 report-only 和强制两条头吗?
可以,规范允许一个站用一条较松的强制策略配一条较严的预览策略。这个面板上有一家两条都发。我们没有逐行比较它那两条策略,所以说不清差多少。
为什么几乎没人用 report-only?
它多一步,还要一个端点,收上来的报告还得有人读。强制头几分钟就能从模板抄好,预览抄不了。这个差就落成了面板上 19 比 1 的样子。
Content-Security-Policy 算 SEO 吗?
不算直接算,但它决定你自己的脚本、样式、字体到底能不能加载。一条策略切断了页面需要的内联脚本,那就是渲染问题;页面渲染错了,搜索引擎和 AI 引擎都会读错。
一条要说清的局限:我们每个站只读了一次头,所以看不到某个站过去是否强制过策略,也没有跟任何 report-uri 去验证端点是不是活的。一个站可能在别的路径上开着 report-only,或者藏在我们没跟的跳转后面。


