我在网站上实施内容安全政策(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控制台中触发以下错误消息:
拒绝执行内联事件处理程序,因为它违反了 遵循内容安全政策指令:&#34; script-src&#39; self&#39; &#39;随机数随机&#39; &#39;严格动态&#39;&#34 ;. “不安全 - 内联”和“不安全”。关键词, 启用哈希(&#39; sha256 -...&#39;)或nonce(&#39; nonce -...&#39;) 内联执行。
有关如何从CSP角度解决此问题的任何建议?我无法更改使用内联事件处理程序添加动态生成内容的第三方库的代码。
答案 0 :(得分:3)
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
属性分配函数是可以的,而不是在HTML元素上设置onclick 属性,而该元素由CSP阻止,因为它将字符串转换为代码。这将起作用并避免CSP违规,但只有在库中有少量内联事件处理程序实例时才有意义;否则这可能会非常繁琐。
作为旁注,您的CSP可能会受益于不支持'strict-dynamic'
的旧版浏览器的回退,类似于this example。