返回

CSP nonce 难题:解决 script 标签安全问题

vue.js

内容安全策略(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,可能仍然报错, 核心原因包括以下几种:

  1. nonce 未正确传递: 浏览器未能在 script 标签中检测到 nonce,或其值与 CSP 策略中设置的 nonce 不匹配。

  2. CSP 配置错误: 可能没有在 CSP 策略中正确指定或使用 'nonce-{generated-nonce}'

  3. 代码生成过程引入的问题: 构建工具,例如 Webpack 或 Vite 在构建过程中可能不总是保持脚本内联时的nonce,或者生成使用 eval() 等构造的代码。

  4. 引入第三方库或插件: 一些第三方库可能动态生成 JavaScript 代码,而且未配置 nonce 。

解决方案与实施

解决此类问题的关键在于排查以上潜在因素,以下是一些推荐的做法。

1. 检查 nonce 生成与传递

首先确认在模板文件中,nonce 值是否被正确生成并通过 csp_nonce() 方法传递。 csp_nonce() 生成的随机值需要能够传递给浏览器端,并且能在服务端配置的策略中使用。如果使用了自定义 nonce 生成器,例如这里的 App\Support\ViteNonceGenerator::class, 需要检查该生成器的实现,保证其能正常运行。

代码示例:

在模板文件的 <head> 标签中添加:

<meta property="csp-nonce" content="{{ csp_nonce() }}">

检查控制台中输出的源代码, 确认是否已渲染。并且该 nonce 在随后的