内容安全策略与动态按钮

3

我正在网站上实现内容安全策略(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控制台中触发以下错误消息:

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

从CSP的角度来看,有什么建议可以解决这个问题?我无法更改添加具有内联事件处理程序的动态生成内容的第三方库的代码。
1个回答

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');

请注意,直接将函数分配给onclick属性是可以的,这与在HTML元素上设置onclick 属性不同,后者会被CSP阻止,因为它将字符串转换为代码。这样做可以避免CSP违规,并且有效,但仅在库中存在少量内联事件处理程序时才有意义;否则可能会变得非常繁琐。
另外,值得一提的是,您的CSP可能会受益于针对不支持'strict-dynamic'的旧浏览器的回退,类似于this example

关于“内容脚本”(指生成HTML内容的JS脚本)主题有一些额外的信息可以在https://developer.chrome.com/extensions/contentSecurityPolicy#interactions找到。该页面很好地讨论了内容脚本的细微差别。 - dnickels

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接