-
Notifications
You must be signed in to change notification settings - Fork 79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inline style bits are very unclear #212
Comments
@mikewest Deciding on the right behavior here is actually blocking some work we're trying to do soonish in Gecko, so it would be good to have some clarity on the spec here... |
Digging through commit logs, we originally made this change in WebKit bug 112270 to address a bug jQuery filed. Their expectation was that something like the following code would result in two green squares, even in the presence of a CSP that blocked inline style (
Based on the tiny experiment at https://jsbin.com/tusohe, it looks like both Firefox and WebKit/Blink have this behavior today, and I think it makes sense to keep its broad strokes (as the alternative would presumably break some set of developers who rely on the existing behavior, along the lines of the jQuery ticket above). I think you're correct, though, that the specs don't make sense together. In WebKit/Blink, we end up doing something that I think equates to adding a flag to the "append" call in step 2.2.2 of https://dom.spec.whatwg.org/#concept-node-clone, noting that the operation is the result of cloning, and then thread that through to a hook that's called on elements when their style attribute changes. If you squint, that hook more or less maps to "the attribute's value must be parsed when the attribute is added or has its value changed" in https://html.spec.whatwg.org/multipage/dom.html#the-style-attribute. Does that seem like a reasonable direction to explore?
The distinction between "parsing" and "applying" in https://html.spec.whatwg.org/multipage/dom.html#the-style-attribute seems like one without a difference, as it looks like "parsing" turns into actual style applied to the element. The intent of the CSP bits there is to prevent the content of the style attribute from being used to style its element, but it's not really clear to me where "styling" happens. I'd appreciate advice about how to phrase this in a way that makes more sense. /cc @annevk @tabatkins who might have opinions. |
If you manipulate the It seems that getting information out of the I don't know how to best define that, since despite asking for a long time, the CSS WG is very resistant to defining clear imperative entry points that they then also use themselves. I suppose we could try again. |
So a few things, from my point of view:
So some plausible approaches to speccing this stuff, assuming we want to preserve the "CSP doesn't apply to .style mutations" and "CSP doesn't apply to cloning" behavior:
I do think we should clarify the CSSOM end of this stuff too, as we do this.. @zcorpan |
Oh great, so Gecko wouldn't do mutation observer callbacks either if you modify the |
Why not? We do them. That is, when the The internal state of the CSSStyleDeclaration doesn't come from parsing, though, which is observable via base URIs and the CSP interactions. |
I'll spend more time on this in the morning, but some quick thoughts now:
The underlying goal of By the same token, we don't have a particular need to prevent developers from cloning nodes with styling that they've poked at via CSSOM (though we do want to ensure that cloning an element with an inline Of the options you present, the first two seem most straightforward to define with the specs that we have. I'm not convinced that threading some creation state through attribute setting would be "much" more complicated, though. That might be worth exploring (if only because it's what Blink is doing at the moment, and it looks like we're using that state in a few other places for reasons that I'm not sure I can justify by pointing to any spec (e.g. https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp?rcl=ae0e0ee4a1b482fc86a7edcd371179c9cfd75d87&l=146, https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp?rcl=36b8552bced16b02fb080f98738087678accf273&l=184, and https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/html/HTMLElement.cpp?rcl=36b8552bced16b02fb080f98738087678accf273&l=430). The fact that this is going to turn out to be complicated to spec means that we might just be doing the wrong thing, though. Maybe I should add some metrics to Chrome to measure how often we actually clone nodes with inline styles in documents whose policy would prevent the style from applying if we just accepted the currently-specced behavior for node cloning... |
I guess that could be defined. Setting the CSP would affect whether the it takes part in the cascade and whether fetches happen. It seems cloning in that case would be fine, as CSP would continue to control the dangerous bits. |
So here is a question: if an element with an inline style attribute in a document that has a CSP that allows inline style is imported or adopted into a document that has a CSP that does NOT allow them, what should happen? |
I filed w3c/csswg-drafts#1559 on the CSSOM issue from #212 (comment) item 2. |
The adoption (import is clone) case should probably fail as well. |
It seems that part of this is tested by http://w3c-test.org/content-security-policy/style-src/inline-style-allowed-while-cloning-objects.sub.html (https://github.com/w3c/web-platform-tests/blob/master/content-security-policy/style-src/inline-style-allowed-while-cloning-objects.sub.html) in a rather weird way (due to conversion from WebKit tests) and the expectations there don't always make sense to me. I'm bringing this up as the last legacy DOM bug at https://www.w3.org/Bugs/Public/show_bug.cgi?id=25529 has mentions of Chrome special casing It'd be great if Chrome could make progress on getting this documented. |
I will be honest this entire discussion is going over my head even after reading it twice. Any chance that someone that understands it better could write some WPT tests or something for the desired behavior? |
Well, that's the problem. It's not clear what the desired behavior is. What's in the spec right now is known to not be it, though. A good start, again, would be Chrome documenting what it implemented, since it clearly didn't implement what the spec the Chrome engineers wrote says.... Then we can at least have a discussion about whether that could be the desired behavior. |
And to be clear, if someone wants it I can describe what Gecko has implemented here. It's not something that was done with CSP in mind at all, and probably has all sorts of weird warts, but I can describe it. Ideally every browser would do that, so we can have some idea of what we're working with. |
Alright I was unable to find someone that knows better so I will try to take over explaining the current Chrome behavior based on my own investigation. Currently when a style attribute is changed, a change reason is passed though (out of kDirectly, kByParser, kByCloning). If the change reason is kByCloning the CSP check is skipped entirely. There a bunch of situations in which a kByCloning reason is used:
Also no CSP checks are done whenever setting a style property: but setting the value of the style attribute does trigger CSP checks: The check is done at the moment the attribute is changed not when the style is applied. The element does not have to be part of the DOM. No extra check is done as far as I can tell if you import the node into a different document. |
Thank you for writing that up. I just realized that #212 (comment) item 3 already describes the Gecko behavior. Please let me know if that's still not making sense. |
Alright so this what I want to go with (pretty much inspired by what @bzbarsky suggested): CSP is checked at parsing and blocks parsing the style attribute. Any direct operations go through.
The idea is that if there is an inline style attribute it needs to pass CSP checks against the document's CSP. If it does we apply the actual https://html.spec.whatwg.org/#the-style-attribute needs to be updated to not check CSP when the source of the attribute change is coming from CSSOM methods.
Overall I think this works but I don't know how to tell if the element has an inline style Thoughts on this approach? |
Which CSP? Especially in the importNode case, where there are two obvious ones.
It dates back to the days when multiple DOM implementations were floating around in the same browser. But it does do various other work in some browsers, for what it's worth (e.g. prototype reparenting in Gecko).
Well, you're asking a slightly nonsensical question is part of the problem. Setting inline style sets the style attribute. That's just how it works. Once you set inline style, the style attribute is set. It sounds like you are going for some sort of concept of "had the style attribute set directly via a string in the original source or page-provided setAttribute call", but I don't see why that concept is relevant, given that for valid CSS values you can achieve via inline style any value you could achieve via setAttribute. Is this really about the "original source" case? What is the real purpose of this check? |
Well the CSP of the
Quoting what Mike said earlier: Basically what I want is to differentiate between cloning a node in these two scenarios:
Another problem is that the inline check is no longer a binary allowed/denied check on the entire page. Since the introduction of Headers
Now if I clone both of these I should prevent the application of the second style BUT in a similar scenario where the styles are coming from CSSOM operations it should not be blocked. The more I think about it the more I think what we should do is to prevent the I did some testing for this and I found an interop discrepancy between Chrome and Firefox.
Here both return |
That seems like a Firefox bug to me. I filed https://bugzilla.mozilla.org/show_bug.cgi?id=1513623 to track this.
This seems like a pretty weird behavior to me. It does have the virtue of being very simple to spec and implement, though.... |
OK. So the idea is to enforce CSP from the new document on the node, even if the original document didn't have CSP blocking inline style. Does this match current UAs?
For the cloning case, where there is just the one CSP involved, I agree that we want to avoid applying the style during clone if the CSP prevents it. The import case is less clear to me, especially around threat models and use cases.
Why? What are the actual threat models this is trying to address?
For same-document cloning this happens automatically if cloning just clones the CSSStyleDeclaration, if any. For cross-document import, where the CSPs may be different, this comes back to threat models. If the original document whitelists "color: green", does not modify it via CSSOM, then imports into a document that only whitelists "color: red", should the green stay? What if the page started with the (allowed) "color: green", then via CSSOM set color to "red" then "green"? What if it started with "color: green" and then via CSSOM set color to "green"? My temptation here would be to go with spec and implementation simplicity unless there are explicit security issues being addressed by adding complexity.
Is it blocked in current browsers? What are the threat models? |
They don't seem to match browser behavior, for one thing: as far as I can tell, the spec requires the style attribute to be parsed, but not applied. How that's supposed to interact with
.style
manipulation is a mystery.Furthermore, there's some confusion about cloning. Spec says a clone should not have its style attr applied, as far as I can tell, but at least some browsers do apply it, and there are web platform tests testing that it gets applied; see web-platform-tests/wpt#5614
Please get this sorted out and bugs filed on browsers as needed....
// cc @mikewest
The text was updated successfully, but these errors were encountered: