如何让脚本在不破坏 CSP 的情况下使用 setAttribute 'style'
How to let script to use setAttribute 'style' without breaking CSP
我正在努力使我的 CSP 政策尽可能严格。我需要在我的包中包含 3d 派对组件。但它使用 element.setAttribute('style'...)
破坏 CSP 的方法。有没有办法允许这个特定的脚本以这种方式内联样式?
2018-10-06更新
这里的原始答案现在现在仍然是正确的——因为 CSP 至少目前在浏览器中实现,仍然没有办法在不指定 unsafe-inline
的情况下完全动态注入样式,而指定 unsafe-inline
基本上否定了 CSP 的全部目的。
但是,CSP3 添加了一个新的 unsafe-hashes
表达式,使您能够允许特定的内联 scripts/styles。参见 https://w3c.github.io/webappsec-csp/#unsafe-hashes-usage, and see Explainer: ‘unsafe-hashes’, ‘unsafe-inline-attributes’ and CSP directive versioning。不过,它还没有在任何浏览器中发布。所以就目前而言,下面的答案仍然完全适用。
允许 style
属性的唯一方法是使用 unsafe-inline
。 style
属性是来自不同的来源还是来自 self
并不重要——除非您有 unsafe-inline
.[=28,否则它们仍将被视为 CSP 违规=]
具体来说,不会对style
属性起作用的一种解决方案是使用随机数或哈希——因为在 CSP 中,随机数和哈希的使用仅定义对于 style
和 script
元素 ;该规范有一个 Hash usage for style elements 部分明确省略了定义样式 属性 .
的哈希使用
因此,即使您在策略中为 style
属性的内容指定了正确的哈希值,您的浏览器仍会将其视为违规处理。
底线是,因为 unsafe-inline
是允许 style
属性的唯一方法——但是使用 unsafe-inline
几乎完全违背了让任何 CSP 策略开始的目的— 从 CSP 的角度来看,唯一安全的解决方案就是永远不要使用 style
属性——既不直接从您自己的 markup/code 也不通过任何第三方代码。
是的,有办法。
这里有很多关于这个的讨论:https://github.com/w3c/webappsec-csp/issues/212
最后简要总结:
CSP is checked at parsing and blocks parsing the style attribute. Any direct operations go through.
使用 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/
对于正在寻找 jQuery 补丁以将样式属性设置更改为设置正确 css 值的任何人,这是我使用的一个(来自 this Github 但有一个重要的错误修复以使其正常工作):
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岁'的问题,为什么topicstarter的问题还没有解决。
在不导致违反 CSP 的情况下使用 element.setAttribute('style', ...)
的问题很容易通过 little hack 解决,该 little hack 在全局范围内将有问题的 element.setAttribute('style')
替换为安全的 element.style.ptop = '...'
。之后你可以在不破坏 CSP 的情况下使用 setAttribute('style')
,这也将修复 jQuery 和其他库。
仅使用 CSP 本身的解决方案将无效,因为:
'unsafe-hashes'
令牌仍未在所有浏览器中得到支持。
- 对于通过“setAttribute('style')”主动使用动态样式的 third-party JavaScript 库,在技术上不可能维护包含数十个哈希的列表。此外,CSP headers 大小有限。
cakeboeing727 started 走上了正轨,可惜新贡献者的想法没有被社会听到。可惜了。
我正在努力使我的 CSP 政策尽可能严格。我需要在我的包中包含 3d 派对组件。但它使用 element.setAttribute('style'...)
破坏 CSP 的方法。有没有办法允许这个特定的脚本以这种方式内联样式?
2018-10-06更新
这里的原始答案现在现在仍然是正确的——因为 CSP 至少目前在浏览器中实现,仍然没有办法在不指定 unsafe-inline
的情况下完全动态注入样式,而指定 unsafe-inline
基本上否定了 CSP 的全部目的。
但是,CSP3 添加了一个新的 unsafe-hashes
表达式,使您能够允许特定的内联 scripts/styles。参见 https://w3c.github.io/webappsec-csp/#unsafe-hashes-usage, and see Explainer: ‘unsafe-hashes’, ‘unsafe-inline-attributes’ and CSP directive versioning。不过,它还没有在任何浏览器中发布。所以就目前而言,下面的答案仍然完全适用。
允许 style
属性的唯一方法是使用 unsafe-inline
。 style
属性是来自不同的来源还是来自 self
并不重要——除非您有 unsafe-inline
.[=28,否则它们仍将被视为 CSP 违规=]
具体来说,不会对style
属性起作用的一种解决方案是使用随机数或哈希——因为在 CSP 中,随机数和哈希的使用仅定义对于 style
和 script
元素 ;该规范有一个 Hash usage for style elements 部分明确省略了定义样式 属性 .
因此,即使您在策略中为 style
属性的内容指定了正确的哈希值,您的浏览器仍会将其视为违规处理。
底线是,因为 unsafe-inline
是允许 style
属性的唯一方法——但是使用 unsafe-inline
几乎完全违背了让任何 CSP 策略开始的目的— 从 CSP 的角度来看,唯一安全的解决方案就是永远不要使用 style
属性——既不直接从您自己的 markup/code 也不通过任何第三方代码。
是的,有办法。
这里有很多关于这个的讨论:https://github.com/w3c/webappsec-csp/issues/212
最后简要总结:
CSP is checked at parsing and blocks parsing the style attribute. Any direct operations go through.
使用 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/
对于正在寻找 jQuery 补丁以将样式属性设置更改为设置正确 css 值的任何人,这是我使用的一个(来自 this Github 但有一个重要的错误修复以使其正常工作):
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岁'的问题,为什么topicstarter的问题还没有解决。
在不导致违反 CSP 的情况下使用 element.setAttribute('style', ...)
的问题很容易通过 little hack 解决,该 little hack 在全局范围内将有问题的 element.setAttribute('style')
替换为安全的 element.style.ptop = '...'
。之后你可以在不破坏 CSP 的情况下使用 setAttribute('style')
,这也将修复 jQuery 和其他库。
仅使用 CSP 本身的解决方案将无效,因为:
'unsafe-hashes'
令牌仍未在所有浏览器中得到支持。- 对于通过“setAttribute('style')”主动使用动态样式的 third-party JavaScript 库,在技术上不可能维护包含数十个哈希的列表。此外,CSP headers 大小有限。
cakeboeing727 started 走上了正轨,可惜新贡献者的想法没有被社会听到。可惜了。