Content-Security-Policy 现在使用 'strict-dynamic'

v3.3.0.beta1 开始,Discourse 实施了“strict-dynamic”内容安全策略 (CSP)。这将消除手动配置 CSP 的需求,并大大提高与标签管理器和广告等外部工具的兼容性。

作为站点管理员,您无需执行任何操作。更改将自动生效,您正在使用的任何外部脚本将继续正常工作。

主题无需更改。少数插件 [^1] 可能需要进行少量调整以兼容此更改(例如 1, 2)。

[^1]:技术上讲:那些通过 register_html_buildererb 模板引入 <script> 元素的插件。

以前为兼容外部脚本而禁用 CSP 的论坛现在应该能够重新启用它,而不会出现任何问题或需要进行配置。

有关技术细节,请参阅此主题:

目前,仍然可以通过禁用“content security policy strict dynamic”站点设置来切换回旧系统。如果您有任何理由这样做,请告知我们!


v3.3.0.beta3 开始,我们将“strict-dynamic”关键字设为 CSP 的强制部分。已移除“content security policy strict dynamic”站点设置,并且“content security policy script src”站点设置已更新,仅存储有效值。

对于管理员,您应该可以在您站点的员工操作日志中找到“content security policy script src”站点设置的先前值(https://<site_url>/admin/logs/staff_action_logs?filters=%7B%22action_name%22%3A%22change_site_setting%22%2C%22action_id%22%3A3%2C%22subject%22%3A%22content_security_policy_script_src%22%7D - 将 <site_url> 替换为您站点的基础 URL)。

26 个赞

更改后,我该如何像以前一样配置 'unsafe-eval'

1 个赞

那里没有变化——你仍然可以添加“unsafe eval”(带引号)到 content security script src 站点设置中。

3 个赞

我看到 content security script src 设置的描述说,启用 content_security_policy_strict_dynamic 将会忽略此设置,所以来这里咨询一下。

3 个赞

描述中写道:

启用 content_security_policy_strict_dynamic 时将忽略主机来源。

其中重要的部分是“主机来源”。“unsafe-inline”不是主机来源,因此它仍然受支持。

话虽如此,我完全同意这很令人困惑。鉴于 strict-dynamic 推出的成功,我们计划移除旧系统。一旦我们这样做,我们就可以自动从列表中删除所有主机来源,这样管理员就会简单得多。:rocket:

5 个赞

好的,感谢您的澄清。

4 个赞

大卫,

只是想澄清一下。

这个新系统可能适用于:

  • 行内脚本
  • 本地托管的完整脚本源

但对于使用“loadScript”调用远程脚本且包含完整远程 URL 的情况,又该如何处理呢?

如果我没记错的话,我好像找不到一种很好的方法来处理这种情况?

那么,对于这些情况,我们是否需要改用以下方法:

  • 将该调用移至行内脚本 OR
  • 将完整源下载为主题资源?

对于前者行内脚本的情况,我猜没有办法保证在调用脚本的元素之前加载该脚本?(就像您可以在 loadScript 之后的 .then 中做的那样)

2 个赞

strict-dynamic 应该能与通过 loadScript 加载的远程脚本配合使用。事实上,这也是我们进行此次切换的主要原因:我们不再需要预先列出每一个外部脚本的 URL。这对于运行广告的人来说尤其有利,因为广告通常会加载大量远程脚本。

您在使用 loadScript 时遇到错误了吗?

3 个赞

我看到了一些错误,但这可能不是原因。让我找个例子。

我主要是在为一次稳定的升级做准备,我知道这涉及到 loadScript 和远程脚本。

您能满足我一下,解释一下代码中用 loadScript 随机调用的远程脚本是如何被“授权”的吗?动态模式 CSP 是怎么做到的?是不是有什么神奇之处?

3 个赞

是的!

MDN 有一个很好的解释和示例。

'strict-dynamic' 源表达式指定,通过使用 nonce 或哈希明确授予标记中存在的脚本的信任,将传播给该根脚本加载的所有脚本。

因此,只要原始脚本是受信任的(通过 nonce),浏览器就允许它无限制地加载任何其他脚本。然后,由于这些脚本是受信任的,它们可以加载更多!


有一个警告,那就是脚本不能是“解析器插入”的。这可以防止 strict-dynamic 被用于 XSS 攻击。

因此,例如,这将被视为“解析器插入”并被阻止:

document.head.appendChild("<script src='https://example.com/xss-attempt.js' />");

但是,以编程方式构造脚本元素不涉及 HTML 解析,不太可能是 XSS 向量,因此是被允许的:

const script = document.createElement("script");
script.src = "https://example.com/script.js"
document.head.appendChild(script);

^^ 这基本上就是 loadScript() 的工作方式

3 个赞

很棒的链接。

好的,差不多了,谢谢!

nonce 是否也包含在 loadScript 渲染的脚本标签中?

2 个赞

不,nonce 仅包含在 Rails 渲染的原始脚本标签中(例如,核心、插件或主题脚本)。

这意味着核心/插件/主题代码是受信任的,并允许插入任何其他脚本。此处不需要 nonce - 浏览器知道是哪个脚本执行了插入,并神奇地知道它可以被信任。

4 个赞

大卫,再次感谢您的时间!

4 个赞

6 个帖子已拆分为新主题:CSP 错误,当通过主题组件添加脚本时