【问题标题】:"inline-style"-Error with Content Security Policy and Javascript“内联样式”-内容安全策略和 Javascript 错误
【发布时间】:2017-02-22 20:47:24
【问题描述】:

我在我的 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

(上报的行号“0”显然不正确)
这是 Opera 和 Chrome 写入控制台的内容:

[仅限报告] 拒绝应用内联样式,因为它违反了以下内容安全策略指令:“default-src 'self'”。启用内联执行需要“unsafe-inline”关键字、哈希(“sha256-ZBTj5RHLnrF+IxdRZM2RuLfjTJQXNSi7fLQHr09onfY=”)或随机数(“nonce-...”)。另请注意,'style-src' 未显式设置,因此 'default-src' 用作后备。

window.onload@test.js:15

(第15行是innerHTML的操作)

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

我的问题:

  • 为什么会出现这个错误? (我想了解为什么它报告“内联样式”,虽然没有内联样式)
  • 如何避免此错误?

我没有实际的机会来更改原始被操纵的部分。我只能改变这一行:

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

附录

对不起,我对此不够清楚:

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

我想要:

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

【问题讨论】:

    标签: javascript content-security-policy


    【解决方案1】:

    更新:

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

    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;
    #sample {
      margin:10px;
    }
    
    #output {
      margin: 10px;
    }
    <div id="sample">
      <div id="affected">
      Sample DIV
      </div>
    </div>
    <div id="output">
      Output: 
    </div>

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

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

    旧答案:

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

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

    这是 default-src 的 documentation

    【讨论】:

    • 我不想这样允许不安全的内联。禁止这样做是有充分理由的。我不想更改标题。我想要两件事:1. 了解为什么报告了不安全的内联样式,而任何地方都没有内联样式。 2. 我想写一个 javascript,不会产生这个错误。
    • 文档说设置 javascript 样式值的行为等同于内联样式。这就是它出现的原因。为了避免这种情况,我认为您可以在样式表中定义类,而不是动态更改样式,您可以添加或删除 css 类。
    • 没有。 p1.style.color = "red"; 正在通过 javascript 设置样式值,但这不会导致任何错误。没有copy.innerHTML = original.innerHTML 行,一切都很好。
    • 是的。为了在设置 copy.innerHTML 后重新创建元素,它必须将样式复制为内联样式,因为它首先转换为文本,然后再从文本转换回来。您可以在技术上制作 DOM 元素的副本,然后直接将其插入到 DOM 树中。
    • 就是这样,这是我想知道的,也是我要求的。请删除您的旧答案,并将您的最后一条评论作为答案发布。
    猜你喜欢
    • 2019-01-19
    • 2020-11-08
    • 2021-07-29
    • 2015-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 2021-12-14
    相关资源
    最近更新 更多