"内联式" - 内容安全策略和Javascript错误

时间:2017-02-22 20:47:25

标签: javascript content-security-policy

我在Apache2配置中使用此命令启用了服务器上的内容安全策略:

Header set Content-Security-Policy-Report-Only "default-src 'self'"

(我将其设置为...-Report-Only仅报告错误,而不会在开发时真正阻止某些内容。)

此设置会产生一个我不明白的错误。但我可以重现它:

这是简化的html代码:

<!DOCTYPE HTML>
<html lang="en">
    <head>
        <script src="/js/test.js"></script>
        <title>test</title>
    </head>
    <body></body>
</html>

如您所见,没有内联脚本,也没有内联样式(根本没有样式)和完全空的主体。

这是Javascript文件test.js:

window.onload = function () {
    //create a paragraph with a red text to have some content
    //in my "real" problem, this part is very much code (more than 1000 lines) 
    document.body.innerHTML = '<div id="original"></div><div id="copy"></div>';
    var p1 = document.createElement('p');
    var t1 = document.createTextNode('some text');
    p1.appendChild(t1);
    document.getElementById('original').appendChild(p1);
    //set some style within this content
    p1.style.color = "red";

    //-----------------------------------

    //make a copy of this content
    document.getElementById('copy').innerHTML = document.getElementById('original').innerHTML;
};

此脚本向正文添加两个div,并将带有文本的段落插入其中一个div。然后它将文本的颜色更改为红色。最后,它会复制此div的内容,并将此副本插入另一个div。

我认为我已经做得很好,但是当我在浏览器中打开此文档时,我在Safari的控制台中报告了此错误:

  

[仅限报告]拒绝应用样式表,因为它的哈希值,其随机数或“不安全 - 内联”样式既不出现在style-src指令中,也出现在内容安全策略的default-src指令中   test.js:0

(报告的行号&#34; 0&#34;显然不正确)
这就是Opera和Chrome写入控制台的内容:

  

[仅限报告]拒绝应用内联样式,因为它违反了以下内容安全策略指令:&#34;默认-src&#39; self&#39;&#34;。 “不安全 - 内联”和“不安全”。关键字,哈希(&#39; sha256-ZBTj5RHLnrF + IxdRZM2RuLfjTJQXNSi7fLQHr09onfY =&#39;)或nonce(&#39; nonce -...&#39;)是启用内联执行所必需的。另请注意&#39; style-src&#39;没有明确设置,所以&#39; default-src&#39;被用作后备。

     

window.onload @ test.js:15

(第15行是对innerHTML的操纵)

当我将任何样式设置为文档的一部分(p1.style.color = "red";),然后复制包含样式部分(copy.innerHTML = original.innerHTML)的部分时,会出现此错误。

我的问题:

  • 为什么会出现此错误? (我想了解为什么它报告&#34;内联样式&#34;虽然没有内联样式)
  • 如何避免此错误?

我没有现实的机会来改变操作原件的部分。我可以改变的是这一行:

document.getElementById('copy').innerHTML = document.getElementById('original').innerHTML;

附录

抱歉,我对此并不清楚:

NOT 想要更改CSP-Header。有一个很好的理由,为什么必须禁止内联式。请参阅XSS attacks and style attributes和类似的问题。

我想:

  1. 了解我的JavaScript代码产生内联样式错误的原因。
  2. 不会产生此类错误的脚本。

1 个答案:

答案 0 :(得分:4)

更新

因为您要从DOMElement转换为文本(通过innerHTML),所以具有已修改样式的任何元素都将转换为内联样式。我已经举了一个例子来说明这一点。

&#13;
&#13;
var el = document.getElementById('sample'), 
output = document.getElementById('output'),
affect = document.getElementById('affected');

affect.style.backgroundColor = "#369";
affect.style.color = "#FFF";

output.innerText+=el.innerHTML;
&#13;
#sample {
  margin:10px;
}

#output {
  margin: 10px;
}
&#13;
<div id="sample">
  <div id="affected">
  Sample DIV
  </div>
</div>
<div id="output">
  Output: 
</div>
&#13;
&#13;
&#13;

因此,当您设置副本的innerHTML时,您将包含已修改元素的样式包含为违反策略的内联样式。

您可以在技术上改为制作DOM元素的副本,然后直接将其插入DOM树。为此,请查看克隆节点的MDN Documentation。在DOM操作不可行的情况下,我的旧答案仍然有效。

旧答案:

根据CSP上的MDN documentation,你可以通过发送以下标题解决它:

style-src 'unsafe-inline' 'self'; default-src 'self';

以下是default-src的documentation