script-src 不写 'unsafe-inline' 就默认禁内联脚本,包括 块、onclick 等事件属性和 javascript: 伪协议;报错“refused to execute inline script”表明策略生效,而非配置错误。

script-src 不写 'unsafe-inline' 就默认禁内联脚本
只要你在 Content-Security-Policy 响应头里写了 script-src 指令,且没包含 'unsafe-inline',浏览器就会直接拒绝所有内联脚本执行——包括 <script>alert(1)</script>、onclick="doIt()"、javascript:void(0)。这不是配置错误,是 CSP 的默认行为。
常见误判:只写 script-src 'self' 就以为安全了,结果上线后一堆按钮点击无响应。原因是你没意识到 'self' 只管外部 <script src="..."></script> 的来源,对内联脚本完全不设限也不放行——它被默认拦了。
-
Refused to execute inline script和Refused to execute inline event handler是标准报错,看到就说明策略生效了 -
script-src 'self' https://cdn.example.com这种写法依然会拦内联,别指望域名白名单能“捎带”放行 - 想保留某段内联逻辑?必须用
nonce或hash显式授权,不能靠漏配来绕过
meta 标签里的 CSP 几乎拦不住内联脚本
用 <meta http-equiv="Content-Security-Policy" content="script-src 'self'"> 在真实环境里基本无效。浏览器解析 <meta> 是同步但滞后的:等它读到这个标签时,前面的 <script></script> 和 onclick 早已执行完毕。
Safari 16.4 之前版本会跳过含 nonce- 的整条指令;Chrome 124+ 已彻底移除对 'unsafe-inline' 在 <meta> 中的支持;只要服务端返回任意 Content-Security-Policy 响应头(哪怕拼错),<meta> 就被无视。
- 本地用
file://打开 HTML 时,CSP 全面关闭,<meta>和响应头都无效 -
default-src 'none'写在<meta>里也起不了作用,因为指令不被完整支持 - 真正要拦内联脚本,必须走服务端 HTTP 响应头,且确保它在 HTML 开头前就发出
nonce 只对 <script> 标签有效,对 onclick 完全无效</script>
nonce 是服务端为每次响应生成的一次性随机字符串,比如 b1967a39a02f45edbac95cbb4651bd12,它只能用于 <script nonce="..."></script> 标签。HTML 属性如 onclick、onload、onerror 根本没法挂 nonce 属性——浏览器不认,策略也不检查。
所以你配了 script-src 'self' 'nonce-b1967a39a02f45edbac95cbb4651bd12',又写了 <button onclick="submitForm()"></button>,这个按钮照样被拦,且控制台报错不会提 nonce,只会说 Refused to execute inline event handler。
- 重构是唯一解:把所有内联事件剥离,改用
addEventListener - HTMX 用户注意:
htmx.config.allowEval = false,否则它内部可能触发eval - Webpack/Vite 构建产物若自动生成内联
onclick(比如某些 UI 库),得查构建配置或换方案
base-uri 和 form-action 不配等于留后门
很多人只盯着 script-src,却忽略 base-uri 和 form-action。这两个指令不显式声明时,默认宽松,攻击者可借此绕过 CSP:
比如没设 base-uri 'self',攻击者就能插入 <base href="https://evil.com">,让所有相对路径资源(包括后续 <script src="app.js"></script>)都加载恶意内容;没设 form-action 'self',表单就能提交到钓鱼地址,CSP 完全不干预。
-
base-uri 'self'防止<base>劫持,必须显式配,不能依赖default-src -
form-action 'self'阻断表单外泄,尤其对含敏感字段的页面是硬性要求 -
object-src 'none'和frame-ancestors 'none'同样不能省,它们和script-src是协同防线,缺一不可
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











