Currently, trying to fetch content served by HTTP inside a service worker results in the request being blocked by the UA. Is this the expected behaviour? If so, which parts of the current specification support it?
I found this comment in a Chrome bug, referring to that:
https://code.google.com/p/chromium/issues/detail?id=448672#c4
It says fetch is not an optionally blockable request context but the _should fetching request be blocked as mixed content_ algorithm and should response to request be blocked as mixed content state passthrough requests should be allowed (maybe with an opaque response, but that's another story).
I believe the intent is to allow network requests that would originally passed mixed content checks to continue passing even if a SW proxies them with evt.respondWith(fetch(evt.request)). I just don't think anyone has implemented that yet.
I also think there are some possible issues with the current spec. The mixed content spec uses this "passthrough request" concept, but that does not exist in the fetch spec. In addition, its unclear if "passthrough request" is something that would be persisted in Cache API, etc.
We either prevent mixed content going into the cache, or need to provide a hook to show a mix warning on response, if the cache is returning a mix asset.
The response has a URL that can be used for that, no?
IMHO it should be allowed in the cache and we can use protocol part of the URL to say if its mixed content. We don't need the hook but simply to warn in the regular way.
Anyway, the main problem is what @wanderview referred to above. What "passthrough request" means and how that works. I once tried to sort this out with @mikewest but we didn't really follow through unfortunately. Probably my fault.
But passthrough request is a concept already defined:
More formally, request is a passthrough request if the following conditions hold [FETCH]:
- request鈥檚 initiator is fetch
- request鈥檚 window is an environment settings object (and, therefore, not no-window)
- request鈥檚 client鈥檚 global object is a ServiceWorkerGlobalScope object.
I thought we did follow through. If the MIX spec is incorrect, tell me and I'll fix it. I think it reflects what we discussed way back whenever we discussed this.
2) request鈥檚 window is an environment settings object (and, therefore, not no-window)
How can this be persisted to Cache? In most cases the window would be long gone. So storing a passthrough request in Cache would strip is passthrough status.
But I guess it mostly doesn't matter if it can be persisted. You can do cache.match(passthroughRequest) to return a cached response. It will match the persisted request even though one is "passthrough" and the other is not. The respondWith() mixed content checking will use then use the original FetchEvent.request to determine if its "pass through" when determining if the response is ok.
I think the only problem is if you did a cache.keys() and then used one of the resulting requests in a fetch(). Then it would no longer be treated as passthrough and fail.
Right? Or have I confused myself again?
2) request鈥檚 window is an environment settings object (and, therefore, not no-window)
How can this be persisted to Cache? In most cases the window would be long gone. So storing a passthrough request in Cache would strip is passthrough status.
Why do you need the window to be persisted? You only need it to decide it is passthrough or not. And you can not even serialize that a request is a passthrough request because this is something transitional, depending on initiator, window and client.
But I guess it mostly doesn't matter if it can be persisted. You can do cache.match(passthroughRequest) to return a cached response. It will match the persisted request even though one is "passthrough" and the other is not. The respondWith() mixed content checking will use then use the original FetchEvent.request to determine if its "pass through" when determining if the response is ok.
I think here, the procedure should be to act as if we were performing a fetch() from network, so match() will run the _should fetching request be blocked as mixed content_ algorithm for the passed request (after checking if there was actually a match), and when retrieving the answer, it will run the _should response to request be blocked as mixed content_ algorithm (although this would be possibly cached and serialized).
I think the only problem is if you did a cache.keys() and then used one of the resulting requests in a fetch(). Then it would no longer be treated as passthrough and fail.
I don't see what is the point here. Do you mind to clarify what is the problem in this case?
@wanderview you are correct. It might be okay that the latter case fails because "passthrough" shouldn't work if there's no window, for instance. So maybe there is no problem here.
@mikewest yeah, I guess I'm still unsure as to whether Fetch should have "passthrough" as a thing or not.
F2F resolution: We should allow passthrough of MIX content and adding to the cache.
We should look at persisting MIX warnings until storage is cleared.
I know it's miserable, but I'd like to revisit this. If there's no implementor interest, we remove it and wait for more developers wanting it.
If we're keeping it, it seems a shame to persist MIX warnings until cache clear. If we can, we should hold back on warnings unless the cached items' body is read.
F2F:
<img> or such), as this may not have involved a request as it may have came from the cacheDo these conclusions require changes to MIX or not? Sorry, it's not at all clear to me what the impact of these three bullets actually is.
If we're keeping it, it seems a shame to persist MIX warnings until cache clear. If we can, we should hold back on warnings unless the cached items' body is read.
In a way, once you have used mixed content everything you do is tainted from that point forward. I don't understand how the browser can show there not being mixed content.
Basically, your argument appears to be that the bit of information you get from whether that request went successful or not does not influence the security of the user. I'm not sure we can make that determination.
@mikewest I'll go through the spec and file an issue against MIX if it looks like changes are needed (and of course let us know if we're wrong).
@annevk It seemed like it was previously suggested that the page would show mixed warnings in a fresh navigation simply because there was a mixed opaque response in the cache. This seems too severe. I realise that you now know if the request was successful or not, but I can retain that information in localstorage and avoid the forever-warning penalty. In fact, I can load a mix image, get its width/height, store that in IDB, and use that in future navigation without penalty.
Yeah, maybe we should show a warning there too. It is rather weird that we don't I think.
Given that we probably can't track when an <img>'s intrinsic width goes into localstorage, are you suggesting a MIX tainting is set for the whole origin until all storage is cleared?
Yeah, basically. Once you get tainted it requires cookie clearance by the user to get rid of it (or sufficiently wide Clear-Site-Data).
Yeah, basically. Once you get tainted it requires cookie clearance by the user to get rid of it (or sufficiently wide Clear-Site-Data).
This basically makes it impossible to build an email site like gmail, no? It will just always be showing mixed content warnings if it ever allows third party images to be loaded.
That is why Gmail proxies. Also for privacy reasons.
The specs already handle what we spoke about in the F2F so I'm closing this. In terms of origin-tainting, let's continue in https://github.com/w3c/webappsec-mixed-content/issues/7
It is not clear to me if we will allow to perform a http request from a service worker. In current Chrome we still reject the fetch when trying to do it. Try it here: https://serviceworke.rs/fetching/ and see results for cors / http and no-cors / http.
Its just not implemented yet.
To be clear, for future readers, we ended up always blocking mixed content in service workers.
Most helpful comment
To be clear, for future readers, we ended up always blocking mixed content in service workers.