如何让脚本在不制动CSP的情况下使用setAttribute'style'

时间:2017-06-17 20:05:38

标签: javascript frontend content-security-policy

我正在努力保持我的CSP政策尽可能严格。我需要在我的包中包含3d party组件。但它使用element.setAttribute('style'...)方法来打破CSP。有没有办法允许这个特定的脚本以这种方式内联样式?

4 个答案:

答案 0 :(得分:2)

2018-10-06更新

这里的原始答案仍然正确目前 - 因为至少目前在浏览器中实现了CSP ,所以没有办法动态注入样式指定unsafe-inline,并指定unsafe-inline基本上否定了CSP的整个目的。

但是,CSP3添加了一个新的unsafe-hashes表达式,使您可以允许特定的内联脚本/样式。见https://w3c.github.io/webappsec-csp/#unsafe-hashes-usage。有关详细信息,请参阅 Explainer: ‘unsafe-hashes’, ‘unsafe-inline-attributes’ and CSP directive versioning 。但是,它还没有在任何浏览器中发布。因此,目前,以下答案仍然完全适用。

允许style属性的唯一方法是使用unsafe-inlinestyle属性来自不同的来源或来自self并不重要 - 除非您拥有unsafe-inline,否则它们仍将被视为CSP违规。

具体来说,不会style属性起作用的一个解决方案是使用随机数或散列 - 因为在CSP中,仅为{{1}定义了nonce和hash使用}和style 元素;规范有一个Hash usage for style elements部分明确省略了为样式属性定义哈希使用。

因此,即使您在策略中为script属性的内容指定了正确的哈希值,您的浏览器仍会将其作为违规处理。

最重要的是,因为style是允许unsafe-inline属性的唯一方法 - 但使用style几乎完全违背了让任何CSP政策开始的目的 - 从CSP角度来看,唯一安全的解决方案就是永远不要使用unsafe-inline属性 - 既不直接来自您自己的标记/代码,也不能使用任何第三方代码。

答案 1 :(得分:1)

是的,有办法。

此处对此有很多讨论:https://github.com/w3c/webappsec-csp/issues/212

最后简要总结了以下内容:

  

在分析时检查CSP,并阻止分析样式属性。任何直接的操作都会通过。

使用setAttribute会调用HTML解析器并触发CSP。

所以,而不是:

.setAttribute("style","background:red"); // needs HTML parsing

您需要:

.style.background = "red"; // direct manipulation

一种方法可行而另一种方法不可行听起来很奇怪,我认为这里的理解是HTML属性和DOM属性之间存在细微的差异。 https://joji.me/en-us/blog/html-attribute-vs-dom-property/

答案 2 :(得分:1)

对于正在寻找 jQuery 补丁以将样式属性设置更改为设置正确 css 值的任何人,这里是我使用的一个(源自 this Github,但有一个重要的错误修复以使其正常工作):< /p>

var native = jQuery.attr;
jQuery.attr = function (element, attr, value) {
    if (attr === 'style') {
        resetStyles(element);
        return applyStyles(element, value);
    } else {
        //native.apply(jQuery, arguments);
        return native(element, attr, value);
    }
};

function applyStyles(element, styleString) {
    if (styleString) {
        var styles = styleString.split(';');
        styles.forEach(function (styleBit) {
            var parts = styleBit.split(':');
            var property, value;
            if (parts.length === 2) {
                property = parts[0].trim();
                value = parts[1].trim();

                element.style[property] = value;
            }
        });
        return styleString;
    }
}

function resetStyles(element) {
    var styleList = [].slice.call(element);
    styleList.forEach(function (propertyName) {
        element.style.removeProperty(propertyName);
    });
}

答案 3 :(得分:0)

奇怪为什么新的问题出现了'3岁'的问题,为什么topicstarter的问题仍然没有解决。

使用 element.setAttribute('style', ...) 而不会导致 CSP 违规的问题可以通过 little hack 轻松解决,该 cakeboeing727 started 将有问题的 element.setAttribute('style') 全局替换为安全的 element.style.ptop = '...'。之后,您可以使用 setAttribute('style') 而不会破坏 CSP,这也将修复 jQuery 和其他库。

仅使用 CSP 本身的解决方案将无效,因为:

  • 并非所有浏览器都支持 'unsafe-hashes' 令牌。
  • 对于通过'setAttribute('style')'主动使用动态样式的第三方JavaScript库,技术上不可能维护一个包含数十个哈希值的列表。此外,CSP 标头的大小有限。

enter image description here 在正确的轨道上,但不幸的是新贡献者的想法没有被社会听到。可惜了。