# 加了 Content-Security-Policy 之后脚本全挂，该先动哪条指令？

**URL:** <https://www.shiqidu.com/t/topic/1912>\
**Category:** 问题求助\
**Tags:** 前端开发, 浏览器, 信息安全\
**Created:** [2026 年11 月 3 日 07:24 UTC](https://www.shiqidu.com/t/topic/1912 "2026-11-03T07:24:17Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

作者： ![shiqidu\_editor](https://www.shiqidu.com/user_avatar/www.shiqidu.com/shiqidu_editor/32/528_2.png) [@shiqidu\_editor](https://www.shiqidu.com/u/shiqidu_editor)\
发布日期： [2026 年11 月 3 日 07:24 UTC](https://www.shiqidu.com/t/topic/1912/1 "2026-11-03T07:24:17Z")

</div>

刚把 `Content-Security-Policy` 写进响应头，首页就白了：统计脚本、聊天组件、自家打包出来的入口 JS 轮流在控制台报拒绝加载。第一反应经常是「先把 CSP 去掉让业务恢复」。MDN《[Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP)》和 web.dev《[Content security policy](https://web.dev/articles/csp)》都把 CSP 写成防 XSS 的纵深防御：用白名单限制脚本等资源从哪来，并限制内联脚本和 `eval` 一类接口。长期方案不该是永久关掉策略。

## 浏览器到底拦了什么

CSP 是一组用分号隔开的指令。跟脚本最相关的是 `script-src`。没单独写时，常会落到 `default-src`。来源可以是 `'self'`、具体主机、`'none'`，以及 nonce / hash 等。页面上一旦存在 `default-src` 或 `script-src`， **未额外放行的内联脚本、内联事件处理器、`javascript:` URL，以及 `eval` / `new Function` / 字符串版 `setTimeout` 等，默认都过不了** 。第三方统计若换了域名、或仍靠页面里塞 `<script>…</script>`，一开策略就全灭，很常见。

web.dev 用控制台报错说明白名单以外的脚本会被拒绝执行。排障时先打开开发者工具：拒绝加载的那一行会写出触犯了哪条 directive、被拦的是哪个 URL（或 inline）。对照 Network / 控制台里的 blocked 信息，比凭感觉把 `script-src` 改成 `*` 靠谱。过宽的域名白名单，两篇文档都提醒过，经常等于没防住 XSS。维护成本也会被第三方脚本域名清单拖垮。

策略应通过响应头下发，并且尽量覆盖所有要保护的响应，不只是首页 HTML。`<meta http-equiv="Content-Security-Policy">` 能救急，但 MDN 写明它不支持全部能力（例如部分指令、Report-Only 也不能靠 meta 送）。

## 先 Report-Only，再 enforce

两篇文档都建议用报告模式摸清现状。响应头换成：

`Content-Security-Policy-Report-Only: …`

策略 **不会拦截** ，但会按你配置的上报地址（`report-to` / 仍可见的 `report-uri` 等）把违规打到服务端。MDN 还写：同一响应里可以同时带 Report-Only 和正式 `Content-Security-Policy`，前者只报、后者执行，方便在现行策略下试下一版。等报告里的域名、内联、`eval` 清得差不多了，再切回强制头。

上线强制策略时，优先收紧的是 `script-src`（以及作为兜底的 `default-src`），按实际需要加 `'self'`、可信 CDN、nonce/hash。MDN 介绍的严格 CSP 示例还会配上 `object-src 'none'`、`base-uri 'none'`。临时甩 `'unsafe-inline'` / `'unsafe-eval'` 能救火，两篇文档都写明应尽快拿掉，否则 CSP 对 XSS 的意义会被掏空。nonce 或 hash 已经出现在指令里时，浏览器会忽略 `'unsafe-inline'`，这点排错时也容易踩。

## 回滚顺序，而不是拆掉整扇门

脚本全挂时，可以按这个顺序收：

- 控制台确认是哪条 directive、哪个资源。
- 若尚未有报告通道，先改 Report-Only 或并行加一条 Report-Only，收集真实违规。
- 只放行证实需要的脚本源。内联改外置文件，或改用 nonce/hash。事件改 `addEventListener`。模板引擎若还在运行时 `eval` 拼字符串，按文档思路换成预编译或 Trusted Types 相关路径，而不是长期挂着 `'unsafe-eval'`。
- 不要把「删除整个 CSP 头」当成长期配置。业务恢复后仍应用白名单兜住注入面。

CSP 也管图片、样式、连接目标、嵌入方（`frame-ancestors`）等，但这次若只有脚本红，先盯 `script-src` / `default-src`，避免一次改十几个指令越改越乱。和跨域凭证那套头不是同一类问题：那边管 Cookie 带不带上，这边管脚本允不允许执行。

用户输入该清洗还是要清洗。CSP 是防漏的一层，文档也写了两者要一起用，不能互相替代。

若报告里反复出现同一条内联或某个第三方域名，先改那一处，再收紧下一刀。整站一次性「全部 `'self'`」往往只会换来另一轮白屏。

你们上 CSP 是一次 enforce 踩坑，还是先走了 Report-Only？统计和打点脚本最后是加域名，还是改成了 nonce？
