带有动态按钮的内容安全策略

Content Security Policy with Dynamic Button

我正在站点上实施内容安全策略 (CSP)。下面是我正在测试的 CSP 策略。

Content-Security-Policy: script-src 'self' 'nonce-random' 'strict-dynamic';

本站使用第三方js脚本库。脚本库在页面上注入动态内容。动态内容具有内联事件处理程序。下面是一个简单的 HTML 页面,其中包含模仿网站 + 第三方库行为的脚本。

<!DOCTYPE html>
<html>
<head>
    <title>CSP Test Page</title>
    <script nonce="random">
        document.addEventListener('DOMContentLoaded', function (event) {
            var el = document.createElement('button');
            el.innerHTML = 'Click Me';
            el.setAttribute('onclick', "doSomething()");
            document.body.appendChild(el);
        });

        function doSomething() {
            alert('I did something.');
        }
    </script>
</head>
<body>
</body>
</html>

动态添加按钮上的内联事件处理程序在 Chrome 控制台中触发以下错误消息:

Refused to execute inline event handler because it violates the following Content Security Policy directive: "script-src 'self' 'nonce-random' 'strict-dynamic'". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.

对于如何从 CSP 的角度解决这个问题有什么建议吗?我无法更改使用内联事件处理程序添加动态生成内容的第三方库的代码。

CSP 阻止所有内联事件处理程序,包括第三方库添加的代码,因此不幸的是,如果不重构与 CSP 不兼容的依赖项,没有简单的方法可以解决此问题。

从长远来看,CSP3 可能会通过 'unsafe-hashed-attributes' 功能提供将事件处理程序中的受信任脚本列入白名单的能力,但这尚未在任何稳定的浏览器中发布。

同时,一种可能的解决方法是在调用外部库后使用内联事件处理程序手动删除该属性。也就是说,您可以执行以下操作:

var el = document.createElement('button');
library.doStuff(el);

// Now that the library has run we will change the DOM to be compatible with CSP.
el.onclick = function() { doSomething() };
el.removeAttribute('onclick');

请注意,对于 CSP,直接将函数分配给 onclick 属性 是可以的,而不是在 属性 上设置 onclick HTML 元素,它被 CSP 阻止,因为它将字符串转换为代码。这将起作用并避免违反 CSP,但只有在库中有少量内联事件处理程序实例时才有意义;否则这会变得非常乏味。

附带说明一下,您的 CSP 可能会受益于不支持 'strict-dynamic' 的旧版浏览器的回退,类似于 this example