内容安全策略随机数不适用于事件处理程序属性

und*_*ned 5 javascript nonce content-security-policy

我正在向一个站点添加 CSP 标头,该站点在采用严格的策略之前还有很长的路要走。有相当多的内联脚本,因此我使用 nonce- 来允许特定的内联脚本。我发现它不适用于onload带有 src 的脚本标记的属性。这是一个例子:

// header:
Content-Security-Policy: script-src self https: 'nonce-d3adbe3fed'

<script async defer src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js" nonce="d3adbe3fed" onload="console.log('onload', _.VERSION)"></script>
Run Code Online (Sandbox Code Playgroud)

完整的工作演示位于https://brave-pasteur-0d438b.netlify.com/

Chrome 给出以下错误:

Refused to execute inline event handler because it violates the following Content Security Policy directive: "script-src self https: 'nonce-d3adbe3fed'". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.
Run Code Online (Sandbox Code Playgroud)

该消息表明应该可以使用随机数启用内联事件处理程序,但据我所知,随机数仅适用于内联脚本。

这只是一个演示,但用例是一个异步/延迟跟踪脚本,它加载跟踪库,然后在onload处理程序中对加载的库进行跟踪调用。

是否可以在一个onload或其他事件处理程序属性上使用随机数,或者我需要更改我的实现吗?使用script-src 'unsafe-inline'orscript-src-attr 'unsafe-inline'不是一个选项,因为这些是我专门试图解决的漏洞。并且将处理程序的内容onload放入脚本标记后面的单独脚本中也不是一个选项,因为脚本是async deferred,并且需要保持这种状态。

und*_*ned 3

如果有一种方法可以nonce在内联处理程序上使用,我将接受演示它的答案。不幸的是,在撰写本文时,我认为不存在。

作为解决方法,以下脚本表现出与具有 async/defer 和 onload 处理程序的脚本相同的行为和计时,同时满足指定的 CSP 策略:

<script nonce="d3adbe3fed">
    let s = document.createElement('script');
    s.src = 'https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js';
    s.onload = () => console.log(_.VERSION);
    document.documentElement.appendChild(s);
</script>
Run Code Online (Sandbox Code Playgroud)

当然,长期的解决方案是完全消除内联脚本,但从短期来看这并不总是可行,最好快速实施更宽松的政策,而不是推迟实施并完全没有 CSP。