Skip to content
This repository was archived by the owner on May 5, 2022. It is now read-only.

Preload and CSP #37

Closed
yoavweiss opened this issue Nov 26, 2015 · 34 comments
Closed

Preload and CSP #37

yoavweiss opened this issue Nov 26, 2015 · 34 comments

Comments

@yoavweiss
Copy link
Contributor

We've ran a few laps around the track with regard to the CSP context that preload based resources should be requested with.

AFAIK, we now have a few non-ideal options in front of us:

  • Deduce outgoing CSP context from as value - the problem with that is that the script as value can map to multiple directives (script-src, child-src and whatever would be the directive for service worker).
  • Assume outgoing CSP context is connect-src and let the consumer enforce the actual policy - that forces authors to define both connect-src and the actual directive for the same resource path, which complicates CSP directive creation.
  • Assume preload requests have no CSP context - that would significantly weaken CSP's promise of limiting ways to leak data to evil.com even if a local script managed to XSS the site in question.

I think that the first option is the least evil and can be resolved by adding a worker-script type or something along those lines.

Thoughts?

/cc @igrigorik @mikewest @annevk

@annevk
Copy link
Member

annevk commented Nov 26, 2015

What needs to happen first is that preload becomes defined in terms of Fetch. Including the concept of "preload store" and such. Then we can more clearly think through what invariants these concepts need to hold in order for things to be secure.

(What I think we concluded last time is that if "as" basically sets request's "type", which seems desirable, the preload store needs to store the "type" along with any data you want to key on, otherwise CSP could be bypassed which would be bad.)

@igrigorik
Copy link
Member

Preload is defined in terms of fetch: https://w3c.github.io/preload/#dfn-obtain-the-preload-resource. You're right that we still need to add the plumbing for preload store, but I don't think that's a blocking concern for this discussion -- we'll need to make sure that appropriate CSP checks are applied when a response is retrieved from the store, but the question we're trying to address here is whether it can get into that store in the first place (step 4 in above processing section).


Assume outgoing CSP context is connect-src and let the consumer enforce the actual policy - that forces authors to define both connect-src and the actual directive for the same resource path, which complicates CSP directive creation.

I think we've already ruled this out. In practice this would mean that connect-src would become a union of all other policies, which is not the outcome we want.

Deduce outgoing CSP context from as value - the problem with that is that the script as value can map to multiple directives (script-src, child-src and whatever would be the directive for service worker).

Right, this is a continuation of whatwg/fetch#93 (comment). Current mapping of as to #concept-request-type is not sufficient to enforce CSP checks before the request goes out.

Here's an attempt at defining a separate as type column: http://output.jsbin.com/teyede/latest - thoughts? One thing that just occurred to me is that the table is missing iframe/frame (whatwg/fetch#166).

@igrigorik
Copy link
Member

bump @annevk :)

@annevk
Copy link
Member

annevk commented Dec 15, 2015

but the question we're trying to address here is whether it can get into that store in the first place (step 4 in above processing section)

I don't understand what this means. I think I stand by my original assertion that defining the characteristics of the store is important in order to figure out whether or not we need a new column.

@igrigorik
Copy link
Member

@annevk as in, whether the request is made in the first place... if the request is blocked by relevant policy, then there is nothing to store. Hence my comment that current mapping of as to #concept-request-type is not sufficient to enforce CSP checks before the request goes out.

@annevk
Copy link
Member

annevk commented Dec 16, 2015

Why is that not sufficient?

@igrigorik
Copy link
Member

Because some of the current as values map to multiple CSP values (e.g. as=script is ambiguous: script-src, child-src; there is no mapping for manifest-src, etc).

Take a look at the table here, where I added as, as a new column: http://output.jsbin.com/teyede/latest.

@annevk
Copy link
Member

annevk commented Dec 17, 2015

Hmm, I think it's a bug in CSP that it doesn't use script for workers. And I think that will be fixed. Preloading manifests seems kind of pointless.

@igrigorik
Copy link
Member

  1. Is there an existing open issue for converting worker's to use script-src? /cc @mikewest
  2. I can buy the manifest argument..
  3. One more outlier: object-src for object/embed doesn't have an unambiguous type equivalent

If we can resolve 1 and 3, then I think mapping as to type would work.

@annevk
Copy link
Member

annevk commented Jan 1, 2016

What would you want to preload in object/embed going forward? They're practically obsolete.

@toddreifsteck
Copy link
Member

Adding Ted from CSP to make him aware. @teddink

@yoavweiss
Copy link
Contributor Author

Looking at the table @igrigorik linked to and following a few conversations I had on the subject, I think there are a bunch of resource types that we would need to address:

  • connect-src: There's no type that maps to that, yet a Web app may want to preload some important data which would be later read by JS. (and here's @paulirish showing exactly that scenario)
  • <iframe>: Its directive is child-src, same as workers. Do we want to distinguish between the two? Seems to me that loading priorities may be different, at the very least. Also, as=worker for an iframe won't be intuitive.
  • <object>: While I agree it's usually not the most urgent of resources, there are scenarios where <object> is still needed (e.g. to improve accessibility of text inside an SVG). As such, it is perceivable that users would want to preload said SVG.
  • HTML imports: Its directive is script-src. Do we want as=script to be the value for HTML imports?

@annevk
Copy link
Member

annevk commented Jan 7, 2016

  • connect-src is the fallback, why would you need type at all?
  • <iframe> is the same as <a>, but neither is really a type. They're navigations. prerender would be more appropriate.
  • Why can't <picture> be used instead of <object>?
  • HTML imports is dead.

@yoavweiss
Copy link
Contributor Author

connect-src is the fallback, why would you need type at all?

OK, so if I want to download an arbitrary piece of data to be then fetched from JS, I just leave as out? I guess that works.

<iframe> is the same as <a>, but neither is really a type. They're navigations. prerender would be more appropriate.

I'm not sure I understand what you mean there. Do you suggest adding a prerender type that is subjected to the child-src CSP directive?

Why can't <picture> be used instead of <object>?

The crux of the approach there is that <picture> can't be used because it would render SVG inside the <img> which is different than it being rendered inside an <object>. I'll let @SaraSoueidan elaborate on why <object> was necessary, since I don't remember the details, other than it enabling the SVG text to be more accessible.

HTML imports is dead.

OK

@annevk
Copy link
Member

annevk commented Jan 7, 2016

Oooh, I think I understand. It seems better to use <iframe> for that SVG use case.

@yoavweiss
Copy link
Contributor Author

One more related issue that comes to mind - what would happen when at some point we would need to add a new type foo? Non-supporting browsers would not know foo, therefore conclude that it is subject to connect-src. At the same time, in a supporting browser, foo is subject to a different directive foo-src.

So, developers have to allow this resource to be downloaded in two separate directives, for a few years. Not very future friendly.

@annevk
Copy link
Member

annevk commented Jan 7, 2016

Isn't that always the case?

@yoavweiss
Copy link
Contributor Author

Yeah, on second thought it's probably not a big deal.

@SaraSoueidan
Copy link

@annevk

I'm not sure if <iframe> is any better than <object> because I’m personally not very informed about the details that differentiate the two. But I do personally use <object> more than <iframe>. Here is what I know and what Yoav mentioned above:

The contents of an SVG image embedded using <picture> cannot be scripted or even animated in some browsers (last time I checked that was Firefox, not sure if that has been fixed).
<object> has many advantages including but the number one being that the contents of the SVG can be scripted and animated—that’s not possible with <picture>.

<object> also comes with the default non-image fallback option, where you can place plain text between the opening and closing tags, and that text would serve as fallback in non-supporting browsers, and can also be read by screen readers, of course. The use case I was particularly interested in was providing text fallback—for example in the form of table data—for SVG infographics.

I discussed that use case in a previous article, and mentioned why it would be useful to have a way to specify multiple SVG sources when using <object>, in a way similar to the multiple sources that allow us to art-direct images with <picture>. Feel free to give the article a scan for the details here. Currently, the only way to do this is to use JavaScript to swap the object source.

That’s the extent of knowledge I can contribute here. I don't know how relevant the "multiple sources for <object>" idea is in this thread. It would indeed be great if we could specify multiple sources to art-direct <object> images, or even <iframe> images, for that matter.

@igrigorik
Copy link
Member

Stepping back for a sanity check on what we're trying to achieve here:

  • I believe we have agreement that preload should be subject to CSP, and the relevant policy is determined by mapping as attribute value to the appropriate Fetch request type -> CSP policy.
    • Current processing algorithm is specced as such already: in step 4 we validate request type against Fetch definition and pass it it to Fetch when initiating the request.

What we need to resolve here is:

  1. There is no type mapping for child-src (frame/iframe/worker scripts).
  2. There is no type mapping for object-src (object/embed).
    • Related: due to (2) an empty as value is ambiguous. Once resolved it'll map to connect-src.

FWIW, I don't think this is the right forum to discuss whether object/embed has a long-term future in the platform.. It exists, developers use it, and we should support those use cases in preload. Once and if that gets deprecated, we can figure out how and if it affects Fetch+Preload.

Concretely, to resolve this issue, we need to extend Fetch type definition to address (1) and (2). Otherwise, I believe all the necessary Preload spec bits are already in place.

@annevk
Copy link
Member

annevk commented Jan 14, 2016

They are supported, just not as first-class citizens. object/embed can embed many different types of content, so they cannot map to a single Fetch type value.

@igrigorik
Copy link
Member

@annevk poor language on my part.. The application can fetch assets under object-src, and preload should allow applications to do the same. How do we enable that? Same for child-src.

@annevk
Copy link
Member

annevk commented Jan 14, 2016

I don't follow your line of reasoning. You're making it seem as if "CSP" has the right answers here whereas it will lead to wrong answers for other things. E.g., <embed> can be used for plugins and for creating browsing contexts. Does preload permit distinguishing those?

@igrigorik
Copy link
Member

No, and that's not the intent. All I'm saying is, developers have existing methods to fetch resources that fall under object-src/child-src policies, and it's perfectly reasonable for them to want to preload such resources while enforcing the same CSP policies; preload should have an as type that maps to those policies. It may be the case that CSP is not sufficiently granular in some cases, but that's not an issue with preload. If and when CSP is extended to add additional types, we'll mirror those. For now, we just need to provide coverage for the existing set.

(and apologies upfront if I'm still missing your point :))

@annevk
Copy link
Member

annevk commented Jan 19, 2016

My point is that I don't think we should make CSP policies a Fetch primitive. And I believe we decided on that elsewhere. Now you're trying to revisit that discussion here. I would be interested in hearing what @ehsan, @sicking, and @mikewest have to say.

@sicking
Copy link

sicking commented Jan 19, 2016

I don't have any opinions about spec-editing issues like what gets specified where or how.

It does make sense to me that for something like <link rel="preload"> (or whatever syntax is used these days) that we also support <link rel=preload as="image"> which would use image-src in CSP.

I assume that either way, if a document contains a <img src="X"> and loading images from X is blocked by security policies like mixed-content-blocking or CSP, that the image is not displayed even if X has been successfully preloaded.

But really, this seems like a discussion for the webappsec WG?

@igrigorik
Copy link
Member

I assume that either way, if a document contains a and loading images from X is blocked by security policies like mixed-content-blocking or CSP, that the image is not displayed even if X has been successfully preloaded.

That's correct. The issue here is actually the other way around:

  • Developer has a policy for child-src that scopes it to X, and connect-src that scopes fetches to Y.
  • Developer wants to preload an HTML resource / worker script.
    • They can't do this because default strategy (connect-src) does not permit access to X.

The knee-jerk developer solution here is to extend connect-src to include Y.. but that's obviously not the outcome we want.

@sicking
Copy link

sicking commented Jan 23, 2016

Yup. Sounds good to me.

@sicking
Copy link

sicking commented Jan 23, 2016

But to be clear, I don't think this requires adding CSP to the fetch spec if Anne wants to avoid that. (But I might very well be misunderstanding Anne's concern)

@kravietz
Copy link

Some of these questions can be raised for Sub-Resource Integrity as well.

@igrigorik
Copy link
Member

@kravietz separate thread: w3c/webappsec-subresource-integrity#26

@sicking right, I'm not proposing we make CSP a first-class citizen in fetch. Rather, I'm just pointing out that current definition of request.type is not sufficient to allow developers initiate preload for worker scripts/iframes/objects/embeds. My proposed solution is to extend type with a two (or more?) new keywords to address this (and under the hood they should map to child-src, connect-src).

@yoavweiss
Copy link
Contributor Author

One more point - while applying the connect-src directive to empty type preloads it came up that CSP changes would be required unless we make sure that the "destination" of such empty type preloads is a "subresource". We should define it as such for the purpose of preload.

@igrigorik
Copy link
Member

Opened #55 to track the developer use cases. Let's solve that and then come back and revisit the CSP integration bits.

@igrigorik
Copy link
Member

Resolved via #57, closing.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants