CSP nonce 难题:解决 script 标签安全问题
2025-01-12 23:27:06
内容安全策略(CSP)中 “script tag” nonce 添加难题
使用内容安全策略(CSP)可以大幅增强 Web 应用程序的安全性。其中一种常见需求是,为 <script>
标签添加 nonce
属性,以防止 XSS 攻击。但是,这个看似简单的任务,在某些情况下可能面临挑战。常见的报错信息是浏览器会拒绝执行一段 JavaScript 代码,因为它违反了设定的CSP策略。
问题剖析: unsafe-eval
报错
错误信息 EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script...
指出CSP中 script-src
指令不接受 'unsafe-eval'
。'unsafe-eval'
允许执行类似 eval()
或 Function()
的字符串,在开发中偶尔用到,但它会增加安全风险。默认CSP政策通常会禁用此选项。使用nonce旨在取代对 'unsafe-eval'
的需求。如果CSP的 script-src
指令包含 nonce-{generated-nonce}
, 就应该允许带有相同 nonce
值的 <script>
标签执行,前提是没有同时设置 'unsafe-inline'
。
但是,即使使用了 nonce,可能仍然报错, 核心原因包括以下几种:
-
nonce 未正确传递: 浏览器未能在 script 标签中检测到
nonce
,或其值与 CSP 策略中设置的nonce
不匹配。 -
CSP 配置错误: 可能没有在 CSP 策略中正确指定或使用
'nonce-{generated-nonce}'
。 -
代码生成过程引入的问题: 构建工具,例如 Webpack 或 Vite 在构建过程中可能不总是保持脚本内联时的nonce,或者生成使用
eval()
等构造的代码。 -
引入第三方库或插件: 一些第三方库可能动态生成 JavaScript 代码,而且未配置 nonce 。
解决方案与实施
解决此类问题的关键在于排查以上潜在因素,以下是一些推荐的做法。
1. 检查 nonce 生成与传递
首先确认在模板文件中,nonce
值是否被正确生成并通过 csp_nonce()
方法传递。 csp_nonce()
生成的随机值需要能够传递给浏览器端,并且能在服务端配置的策略中使用。如果使用了自定义 nonce 生成器,例如这里的 App\Support\ViteNonceGenerator::class
, 需要检查该生成器的实现,保证其能正常运行。
代码示例:
在模板文件的 <head>
标签中添加:
<meta property="csp-nonce" content="{{ csp_nonce() }}">
检查控制台中输出的源代码, 确认是否已渲染。并且该 nonce 在随后的