Skip to content
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

Foreign fetch vs non-credentialed requests #878

Closed
mkruisselbrink opened this issue Apr 12, 2016 · 41 comments
Closed

Foreign fetch vs non-credentialed requests #878

mkruisselbrink opened this issue Apr 12, 2016 · 41 comments

Comments

@mkruisselbrink
Copy link
Collaborator

mkruisselbrink commented Apr 12, 2016

As currently specified foreign fetch doesn't play together well with non-credentialed requests. In a world without foreign fetch, a website on origin A can fetch something from origin B without credentials, and there is no way (modulo fingerprinting) for B to associate that request with its cookies. If B can intercept the request with foreign fetch this is no longer the case as B itself was fetched with credentials, and can make credentialed requests and access data that was cached using credentials. There are a few options here:

  • Live with this: non-credentialed requests aren't an important security/privacy boundary since B can use fingerprinting etc anyway to track things and associate requests with credentials.
  • Completely disable foreign fetch interception of non-credentialed requests. This would be very unfortunate as things like fonts are always fetched without credentials, so this would disable a major use case of foreign fetch.
  • Require origin A to opt in to having its non-credentialed requests be intercepted by a foreign fetch service worker. This would be rather unfortunate as well, as it would largely get rid of the transparent nature of foreign fetch, making it much less powerful.
  • Somehow make it possible for origin B to say "this service worker does not need credentials". In the case of something like the fonts use case this would be done by adding an extra flag to the Link: header that installs the foreign fetch capable service worker. The effect of this flag would be for the service worker to be isolated in effectively its own origin. This origin will never be able to make non-credentialed requests. If a service worker isn't registered with this flag it won't be able to intercept non-credentialed requests.
@mkruisselbrink mkruisselbrink modified the milestone: Version 2 Apr 12, 2016
@annevk
Copy link
Member

annevk commented Apr 14, 2016

I think we decided to "live with this" right? How can this be v2? Is that because foreign fetch is somehow v2?

@wanderview
Copy link
Member

I thought foreign fetch was v2.

@ehsan
Copy link

ehsan commented Apr 14, 2016

I think we decided to "live with this" right?

We did? Does that mean that we're OK breaking no-credentials CORS fetches completely?

@mkruisselbrink
Copy link
Collaborator Author

I'm fine with that decision, but at the F2F the conclusion was that it probably would be a good idea to run this by some security people so we don't run into any surprises when/if they later discover that we broke some guarantees around no-credentials CORS fetches.

@metromoxie @mikewest: either of you want to weigh in on this? We're trying to figure out what to do about no-credentials CORS requests in the context of foreign fetch.

@annevk
Copy link
Member

annevk commented Apr 15, 2016

Yeah, I also discussed this on the WebAppSec list: https://lists.w3.org/Archives/Public/public-webappsec/2016Jan/thread.html#msg116 (our design has changed a little bit since then, but it's still effectively the same). I did not get as much feedback as I would like though, so asking again here doesn't hurt, but I feel pretty confident with the current approach and I have the feeling I'm generally the most conservative when it comes to the same-origin policy.

Also, I don't think we can consider this type of communication at the same level we consider network APIs. Folks are trying to do that with the cache API, and that kind of reasoning just doesn't apply perfectly. This is basically all client-side code talking to each other.

@jakearchibald
Copy link
Contributor

In our first discussion about this, I was aware that we were leaking some credentials as B's SW was fetched via SW, but I hadn't appreciated that B could turn every no-credential request into a credential request. I'm sure @annevk made this clear at the time, but it didn't sink in.

If we decide that no-credential requests are only designed to protect B and not A, this isn't a problem. It's B's cookies that are used after all.

@annevk
Copy link
Member

annevk commented Apr 15, 2016

The reason we have requests without credentials is to simplify the setup for a fetchee to share its data and to make that more common case reasonably safe. They do not protect the fetcher, since the credentials are from the fetchee.

@jakearchibald
Copy link
Contributor

I vote "live with this" then. I probably made too big a deal of it at the F2F.

@annevk
Copy link
Member

annevk commented Apr 15, 2016

A thing we could add for defense-in-depth is more registration options. Optin for methods, headers, credentials, etc. so you don't have to write JavaScript to filter out the "bad" requests.

@jakearchibald
Copy link
Contributor

We spoke about that too, but again it's only for B's protection.

@annevk
Copy link
Member

annevk commented Apr 15, 2016

Yes, the ease of writing a foreign fetch service workers. (Note that all of CORS is about fetchee's protection too. Fetchee's protection is not unimportant.)

@wanderview
Copy link
Member

I thought allowing B to send credentialed requests for things like fonts hosted on B created a tracking issue. Is this not the case? In fact it seems B could send credentialed requests to C to track the user, which is not something the server could do.

A thing we could add for defense-in-depth is more registration options. Optin for methods, headers, credentials, etc. so you don't have to write JavaScript to filter out the "bad" requests.

Yes, this is basically what I'm asking for in issue #880. Some basic protections against potentially dangerous requests that you should opt-in to.

@joelweinberger
Copy link

I lean towards "as is," since it really is B foot-gunning itself, although it does seem a bit too easy for a developer to go awry. I was wondering about having separate handler registrations for 'credentialed' and 'non-credentialed' requests, which I think maybe what @wanderview is suggesting.

Also, perhaps I'm just confused (or maybe this is orthogonal), but what happens if B returns an opaque, credentialed response from C? That is, A makes a non-credentialed request to B. B's SW's foreign-fetch handler returns an object it earlier fetched from C, with credentials. This seems like a particularly weird relationship, because C thought it was responding to a credentialed request, and A thought it was making a non-credentialed request, and neither one can possible know about what's going on. I'm afraid I'm just confused, though, and this probably doesn't matter.

@annevk
Copy link
Member

annevk commented Apr 15, 2016

@wanderview the moment you allow B to be credentialed you have that problem. And given that existing service workers are credentialed it seems like that will be the common case.

@metromoxie it depends on what mode A used. If A used "cors", you'd get a network error. If A used "no-cors", A would just get an opaque response, as it always would in this scenario.

@wanderview
Copy link
Member

@wanderview the moment you allow B to be credentialed you have that problem. And given that existing service workers are credentialed it seems like that will be the common case.

But this is not something you can do with same-origin service workers today. And letting someone setup a tracker across all sites referencing a third-party font, etc, seems quite bad, no? It doesn't even need an iframe so protections against 3rd party iframes won't work.

If we change registration to choose "credentialed" vs "non-credentialed", the worker would not be able to be shared with normal same-origin operations any more. Since we can't trace async operations back to their source event easily we would need to prevent credentialed operations everywhere in the service worker.

A little bit more magical would be to spin up a second worker thread for non-credentialed and flip a flag on ServiceWorkerGlobalScope. Any code running in this restricted instance of the service worker would fail credentialed network requests.

@annevk
Copy link
Member

annevk commented Apr 15, 2016

And letting someone setup a tracker across all sites referencing a third-party font, etc, seems quite bad, no?

How are you going to prevent that though if you still give the ability to do just that? Seems like irreconcilable goals.

And what exactly is the attack model here? If B is used everywhere and wants to track, it can already do so, with or without credentials, and even better the moment we let it run scripts.

@wanderview
Copy link
Member

And what exactly is the attack model here? If B is used everywhere and wants to track, it can already do so, with or without credentials, and even better the moment we let it run scripts.

Well, as I understand it, CSS @fontface loads without crediantials. If B is hosting a font, suddenly it can now register a foreign fetch service worker and get a tracking cookie delivered with all those font loads.

I guess what you are saying, though, is that since B can run script in the service worker anyway it could just store its own cookie in IDB and send it along in the URL query field. Is that correct?

@annevk
Copy link
Member

annevk commented Apr 15, 2016

Yeah, once you allow script, all bets are off. This is basically turning @font-face (and all other fetchers) into <iframe> elements. This might be surprising to certain As, but it doesn't really change anything fundamentally. If A doesn't want this, it should not use third parties.

Now that we've gone back and forth a bit on it though, I could imagine the media having a field day with this once they find out.

@wanderview
Copy link
Member

I know that fonts are a main use case, but we could restrict ForeignFetchEvent to just certain types of network requests. If we restricted to xhr/fetch we could still allow people to build progressively enhanced REST APIs.

@annevk
Copy link
Member

annevk commented Apr 15, 2016

I'm happy to discuss further, but at this point I think I either need to see a concrete proposal or talk to you (and others) to further flush out some kind of alternative plan (e.g., a video conference). This doesn't work too well.

@wanderview
Copy link
Member

On the other hand, if we want to just "live with it", we should get some feedback from the security community first.

@annevk
Copy link
Member

annevk commented Apr 16, 2016

Sure, if only they could be magically summoned and bring us all the answers 😊

@bsittler
Copy link

Do we also have this same problem when foreign fetches originate in different-(eTLD+1) IFRAMEs while third-party cookies are blocked?

@annevk
Copy link
Member

annevk commented Apr 16, 2016

Third-party cookie blocking is not something that's part of standards so it hasn't really come up. I suspect that when you enable that, you don't get foreign fetch.

@wanderview
Copy link
Member

The more I think about this the more I agree with the approach that requires origin A to opt-in to foreign fetch interception via a header or meta tag. But obviously I'm not a security guy, etc.

@jakearchibald
Copy link
Contributor

https://twitter.com/josh_triplett/status/781482468486488064 long thread, but a lot of concern that an <img> could now allow another origin to execute JS.

@annevk
Copy link
Member

annevk commented Sep 29, 2016

The angle being forums that are okay with their users being tracked, but not ddos'd? Hmm.

@jakearchibald
Copy link
Contributor

I think the concern is about ddosing another third party.

@joshtriplett
Copy link

joshtriplett commented Sep 29, 2016

@annevk Right, DDoS was the big concern.

Suppose you have a forum or other site that allows the posting of safe non-active content only, but allows you to embed third-party images. Many sites do allow that, and consider img tags safe. (I agree that they should take more care to avoid tracking, yes.) If someone linked to 100 images in an effort to DoS some other site, that's easy to notice and ban. But someone could link an image or two from a cooperating server, that image could serve a foreign-fetch service worker, and that foreign-fetch service worker could make a large number of requests to third-party sites. And as long as the image itself shows up correctly, it's harder to notice the subtle DDoS via the foreign-fetch service worker (complete with amplification attack).

One possible fix would be to require the main first-party site to opt into (or, at least, allow them to opt out of) allowing foreign-fetch service workers for some or all subresource requests via CSP.

@annevk
Copy link
Member

annevk commented Sep 29, 2016

Sure, I understood the attack. Not entirely sure I found it convincing.

@jakearchibald
Copy link
Contributor

F2F: Between the ddosing worry, and the credentialed thing, should foreign fetch be opt-in by the fetchee?

@delapuente
Copy link

Sorry @jakearchibald , do you mean the fetcher (who that makes the fetch)?

@jakearchibald
Copy link
Contributor

Yes

@annevk
Copy link
Member

annevk commented Mar 31, 2017

I think the main problem with foreign fetch is the third-party cookie problem as I outlined on blink-dev. Safari has a fundamentally different way of dealing with third-party storage that is arguably better for users. If user agents aligned on that, much of foreign fetch would not work well due to it being double-keyed. So we'd need to work that through first and figure out the more fundamental architecture around third-party storage.

@wanderview
Copy link
Member

I think the main problem with foreign fetch is the third-party cookie problem as I outlined on blink-dev. Safari has a fundamentally different way of dealing with third-party storage that is arguably better for users. If user agents aligned on that, much of foreign fetch would not work well due to it being double-keyed. So we'd need to work that through first and figure out the more fundamental architecture around third-party storage.

Are there any proposals for supporting double-keying here? I am doubtful. Fundamentally:

  1. Double-keying is designed to prevent 3rd party origins from maintaining shared state.
  2. Foreign fetch is about enabling 3rd party origins to maintain state to enable optimizations or other features.

These are diametrically opposed. I am having a hard time envisioning a solution that satisfies both goals.

From my perspective foreign fetch is a progressive enhancement. It can be present for credentialed requests where the user is willing for 3rd party origins to maintain state about them. It can also be disabled if the user signals they don't want 3rd party origins to maintain state.

@annevk
Copy link
Member

annevk commented Mar 31, 2017

The problem as I said before is that Safari uses double-keying by default for third-party storage (unless there was a first-party visit). As that's a better model than what other browsers deploy, I don't think we should introduce this feature if that forces them to adopt a less a model that's not as great for privacy. I actually think we should adopt their model in Firefox too.

@wanderview
Copy link
Member

As that's a better model than what other browsers deploy, I don't think we should introduce this feature if that forces them to adopt a less a model that's not as great for privacy.

Why would it force them to do anything? Safari could simply not implement foreign fetch or enable it with similarly double-keyed storage. It would be less effective, but that's already a trade-off they get with 3rd party iframes using IDB, etc.

Again, what is the alternative?

@annevk
Copy link
Member

annevk commented Mar 31, 2017

Why would it force them to do anything?

Depending on how sites make use of this and start relying on it, Safari might be forced to adopt other models and other browsers would be constrained from implementing models that are better for privacy.

An alternative would be acknowledging that the Safari model is better and gradually move everything to be like that.

@jakearchibald
Copy link
Contributor

F2F: Need to think about opt-ins and restricting by type.

TODO: go through the meeting notes and write up issues.

@jakearchibald jakearchibald self-assigned this Apr 4, 2017
@jakearchibald
Copy link
Contributor

For me: write up issue and get a smaller group together to discuss.

@jakearchibald
Copy link
Contributor

Closing due to removing foreign fetch.

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

No branches or pull requests

10 participants