Safari 11.0.3无法识别内容安全策略哈希

时间:2018-02-22 23:03:46

标签: safari content-security-policy

我有一个带有以下指令的元标记:

<meta http-equiv="Content-Security-Policy" content="base-uri 'self'; script-src 'self' 'sha256-s5EeESrvuQPpk2bpz5I3zn/R8Au2DYB1Z+YUH9p0fUE=' 'sha256-PYYfGnkbZ44B9ZBpgv8NbP3MXT560LMfrDSas2BveJo=';">

然后我在页面下方有两个内联脚本,每个脚本应该匹配策略中生成的一个sha。

在Chrome和Firefox中,我没有投诉,我的脚本按预期运行。

在Safari版本11.0.3(13604.5.6)中,出现以下错误:

Refused to execute a script because its hash, its nonce, or 'unsafe-inline' does not appear in the script-src directive of the Content Security Policy

我很困惑为什么!

不幸的是,我无法用它内部的问题产生最小的可重复回购 - 较小的示例在Safari中为我工作,所以它让我相信它与我的应用程序中的特定内容有关,可能与第二个相关我在下面试过的东西。

非常感谢任何帮助!

我尝试过的事情:

是否支持哈希?

根据this Stack Overflow postSafari release notes,支持哈希的CSP 2.0在Safari 10中实现

正确的字符集?

以前,我看到的问题是因为我在计算基于UTF-8字符集的哈希值,但是在没有charset元标记的情况下将JS输出到浏览器。我的JS中的特殊字符被破坏,并且在浏览器尝试计算时会导致shas的差异。

我不相信这会影响我,因为Chrome和Firefox看不出任何问题,但也许我在这里错了?

Safari的

unsafe-inline,然后允许哈希在Chrome和Firefox中覆盖它?

根据CSP规范,unsafe-inlineignored if a hash or nonce is present。 Safari 11也遵守此规定,因此添加unsafe-inline关键字无效

2 个答案:

答案 0 :(得分:2)

原来这是一个字符集问题。

我设法获得了一个可重复性最小的问题(经过一些试验和错误,并且运气很好!)并且发现我的一个角色在Safari中呈现之前和之后都有不同的sha。

在Safari中呈现之前,角色如下:

Before Safari Rendered the Character

在Safari渲染了角色后,它是以下(即使在代码的源代码中):

After Safari Rendered the Character

奇怪的是,Chrome和Firefox都没有这个问题,因此它必须是Safari渲染后对字符进行规范化,或者在浏览器之间计算sha256哈希时的差异。

解决方案是关闭UglifyJS中的字符压缩,使字符保持为\uF900,而不是压缩到上图中的单个字符。

我在webpack.config.js文件中使用以下选项实现了这一点:

new UglifyJsPlugin({
    uglifyOptions: {
        output: {
            // necessary to stop the minification of escaped unicode sequences into their actual chars.
            // some unicode breaks CSP checks in safari
            ascii_only: true,
        },
    },
}),

我已向Apple报告,看看他们是否会考虑修复此问题。

答案 1 :(得分:0)

另一种解决方案是确保脚本中的字符串已标准化。可以使用String.normalize在JavaScript中实现。

规范化确保每个Unicode字符均以其规范(NFC)形式表示,这似乎使Safari中的CSP哈希比较得以实现。因此,如果您要处理任何可能使用重音符号,非拉丁文字等的文本,则对字符串进行标准化是个好主意。