带有事件处理程序散列的内容安全策略在 iOS Safari 上不起作用

Content-security-policy with a hash for an event handler does not work on iOS Safari

有没有办法让 iOS Safari 尊重 'unsafe-hashes' 内联事件处理程序的内容安全策略?除了使用 'unsafe-inline' 之外还有其他解决方法吗?

iOS Safari 14.3 报告“script-src”的 CSP 违规,而 Firefox 和 Chrome 在桌面上以及 android 按预期工作。

目前看来无法替换内联事件处理程序,因为事件处理程序是由 JSF/Mojarra 生成的。

这是测试页面:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html
    xmlns="http://www.w3.org/1999/xhtml"
    xml:lang="en"
    lang="en"
>

    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1"/>
        <meta charset="utf-8"/>

        <!-- works in Firefox on Desktop, Chrome on Desktop, Firefox on Android, Chrome on Android -->
        <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-hashes' 'sha256-9tftRELs2TcRhB+bln6nFx6j6k3J4ESyFzUOJgDFjew=' 'report-sample'; report-uri /csp-report"></meta>
        <!-- works in Firefox on Desktop, Firefox on Android -->
        <meta http-equiv="Content-Security-Polic1" content="default-src 'self'; script-src 'self'                                 'sha256-9tftRELs2TcRhB+bln6nFx6j6k3J4ESyFzUOJgDFjew=' 'report-sample'; report-uri /csp-report"></meta>
        <!-- works in Firefox on Desktop, Chrome on Desktop, Firefox on Android, Chrome on Android -->
        <meta http-equiv="Content-Security-Polic2" content="default-src 'self'; script-src 'self'                 'unsafe-hashes' 'sha256-9tftRELs2TcRhB+bln6nFx6j6k3J4ESyFzUOJgDFjew=' 'report-sample'; report-uri /csp-report"></meta>
        <!-- works in Firefox on Desktop, Chrome on Desktop, Firefox on Android, Chrome on Android, iOS Safari -->
        <meta http-equiv="Content-Security-Polic3" content="default-src 'self'; script-src 'self' 'unsafe-inline'                                                                       'report-sample'; report-uri /csp-report"></meta>
    </head>

    <body>

        <a href="#" onclick="alert('test'); return false">Test</a>
    </body>

</html>

这是迄今为止我自己收集到的有关该主题的信息。

在 CSP 级别 2(这是最新规范)中,您不能,请参阅 https://www.w3.org/TR/CSP2/,第 7.15 节:

每当用户代理从内联事件处理程序执行内联脚本时,用户代理不得执行脚本,并且必须报告违规。

也就是说,符合 CSP3 标准的浏览器在理论上可以让您使用“不安全哈希”指令,请参阅 https://www.w3.org/TR/CSP3/#changes-from-level-2,具体来说,第 8 点:

'unsafe-hashes' 源表达式现在将允许事件处理程序、样式属性和 javascript: 导航目标匹配哈希。

查看兼容浏览器列表:https://caniuse.com/?search=unsafe-hashes

作为确认,我在 Chrome 92 上用这个简单的 HTML 页面试了一下:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-hashes' 'sha256-WOdSzz11/3cpqOdrm89LBL2UPwEU9EhbDtMy2OciEhs=';">
  <button onclick="alert('foo');">click me</button>
</body>
</html>

它起作用了,当我点击按钮时显示警报。

所以,我认为它在 Safari 上不起作用是正常的,因为它被列为不兼容的浏览器。奇怪的是它适用于 Firefox 91,它也被列为不兼容。也许 caniuse.com 上的信息不完整。

我想在 CSP 级别 3 得到广泛支持之前,我们只需要遵守 CSP 2,这意味着将我们的脚本放在单独的 JS 文件中并从那里附加处理程序。另一方面,这样做也恰好更安全(因此新指令中的“不安全”)。