关于html:带动态按钮的内容安全策略

Content Security Policy with Dynamic Button

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html>
<head>
    CSP Test Page
    <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.');
        }
   
</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'功能将事件处理程序中的可信脚本列入白名单的功能,但这尚未在任何稳定的浏览器中提供。

与此同时,一种可能的解决方法是在调用外部库后使用内联事件处理程序手动删除该属性。也就是说,你可以这样做:

1
2
3
4
5
6
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属性分配函数是可以的,而不是在HTML元素上设置onclick属性,而该元素由CSP阻止,因为它将字符串转换为代码。这将起作用并避免CSP违规,但只有在库中有少量内联事件处理程序实例时才有意义;否则这可能会变得相当乏味。

作为旁注,您的CSP可能会受益于不支持'strict-dynamic'的旧浏览器的回退,类似于此示例。