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

dni*_*els 3 html content-security-policy

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

Content-Security-Policy: script-src 'self' 'nonce-random' 'strict-dynamic';
Run Code Online (Sandbox Code Playgroud)

该网站使用第三方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>
Run Code Online (Sandbox Code Playgroud)

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

拒绝执行内联事件处理程序,因为它违反了以下内容安全策略指令:“script-src 'self' 'nonce-random' 'strict-dynamic'”。启用内联执行需要“unsafe-inline”关键字、哈希值(“sha256-...”)或随机数(“nonce-...”)。

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

小智 5

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');
Run Code Online (Sandbox Code Playgroud)

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

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