Open iVanlIsh opened 4 months ago
I don't currently have a strong opinion on this, but would like to share some general thoughts / questions that might need consideration.
<img>
or <iframe>
). This might make something that should be easy and trivial, more convoluted and complicated (e.g. rendering a static HTML website).<script>
tag at the beginning of the document doing a targetAddressSpace
fetch will "unlock" the address space for any subsequent statically rendered <img>
and <iframe>
tags pointing at the same origin)?<form>
element posting to a singular endpoint triggering a side effect.<form>
element needs access to a private address space origin, unlocking access to that private address space origin for all elements might allow an attacker to effectively exploit an otherwise benign injection attack. Think a markdown image pointing at ![You're p0wned](http://192.168.0.1/restart.cgi)
which will restart your router every time your browser loads this image as part of the document that unlocked PNA to support aforementioned <form>
element.I think one way to resolve many (but not all) issues would be to provide an API to "unlock" an origin for PNA requests without having to actually send a request. Bonus points if that API can be used from static HTML. I think an earlier proposed CSP would have done exactly that. Was that idea discarded? If so, why?
Edit: The title of the post seems to imply that this proposed change is related to the current ServiceWorker limitations. It's unclear to me how those two things are related. Some elaboration would be greatly appreciated :)
Why we cannot use service worker: The mixed content check is triggered before the requests go into service worker, so that the changes adding inside service worker, like adding targetAddressSpace
, cannot be seen by the mixed content checker.
The word "unlock" might be not that much accurate. Our current idea is when one "fetch()" has been triggered with targetAddressSpace
private/local for a certain host. This targetAddressSpace
will be cached and applied to requests ( e.g. for HTML or
One pros for this is, the website now have chance to control when the permission prompt will be shown.
Wouldn't that bypass one of the CORS design aspects of only guaranteeing things for a given URL, not for a set of paths?
I'm also somewhat surprised that we now have fetch()
triggering UI. For all the places fetch used to do that it has typically been deemed a mistake. It also seems like a layering violation and given the timing around network fetches will likely not lead to a good user experience (it would also be harder to require the user to have prior interaction and such).
The word "unlock" might be not that much accurate. Our current idea is when one "fetch()" has been triggered with targetAddressSpace private/local for a certain host. This targetAddressSpace will be cached and applied to requests ( e.g. for HTML or
Yes, that was my understanding crafting the response. "Unlock" was probably a poorly chosen word. I do think that all concerns / thoughts raised in my response are valid and applicable to this scenario though.
One pros for this is, the website now have chance to control when the permission prompt will be shown.
Could you elaborate a little more on this aspect? It doesn't appear obvious to me why that would be the case.
You mean compared to the CSP solution or compared to having to specify targetAddressSpace
explicitly on each fetch / API call? For the former it seems like the actual UI would only trigger as part of the actual request (timing would be virtually equal). Not to mention that it would be possible to add the meta elements just before sending the request anyway. In the latter case it should be obvious that there is much more granular control about when and to which requests to apply PNA.
I would still like to understand how this proposal differs from the CSP proposal and why you believe this would be the better approach.
Why we cannot use service worker: The mixed content check is triggered before the requests go into service worker, so that the changes adding inside service worker, like adding
targetAddressSpace
, cannot be seen by the mixed content checker.
Thank you for clarifying. This was my understanding. It isn't obvious to me how this proposal will help with that. Or am I confused and this proposal is entirely unrelated to the service worker issue?
It is also unclear to me how that particular behavior is a problem in of itself. If the application believes a given URL is in the private or local address space, it should apply the correct targetAddressSpace
option to the request within the main application context. The mixed content checker can then perform it's check accordingly. As far as I understand it is not possible for a service worker to make changes to the URL or targetAddressSpace
of that particular request after the fact. A service worker can choose to issue a different request in response to the fetch event, but that would be a new request with a new (and potentially different) URL, a new options bag and it's own mixed content check. It would be up to the service worker author to correctly apply the targetAddressSpace
option again if they believe the request to be going to a private or local address space origin. This would require PNA/PermissionDialog support within ServiceWorker though, which I if I am not mistaken is at this point not implemented.
I think I now understand: What you are saying is that it's not possible to use service worker as a solution to the problem of how to add targetAddressSpace
to non fetch()
-API fetch requests. The reason being because a mixed content check will get applied to them before the service worker fetch event triggers and the service worker has the opportunity to re-issue a new request with the correct targetAddressSpace
option set. That makes a lot of sense.
It seems like the most comprehensive approach would be to move the mixed content check to "before the request goes onto the wire", i.e. to the time of egress from the service worker. I'm not going to pretend I understand all of the implications (e.g risks and effort) of such a change, but it appears that the mixed content policy is intended to prevent insecure requests from unknowingly to the user traversing networks where they could be intercepted, observed, manipulated, etc. As long as a request doesn't traverse a network, it is not subject to those threats. A request to http://somedomain.com
passing through a service worker should not be subject to the mixed content policy before it is about to leave the service worker and go onto the wire/air. All mixed content checks should happen at the time of egress from the service worker, not at the time of (or before) ingress.
At a time before service workers it may have made sense to do the mixed content check at the time of request creation, but today it is not a given that a request will actually end up on a wire just because it was instantiated. Moving the mixed content check to the time of or just before egress seems to be the "correct" solution here.
This would also enable service workers to provide responses to insecure requests for which they may have obtained a response previously or via a way different than fetch()
without opening the application up to potentially sending an insecure request onto the wire.
E.g. in a world with egress-timed mixed content checks, the following would be possible:
// in application.js
// We would like our SW to handle this request, but never accidentally send it onto the wire
fetch('http://192.168.0.1' /* no targetAddressSpace set */)
// in sw.js
addEventListener('fetch', (event) => {
if (isPrivateAddressSpace(event.request.url)) {
return event.respondWith(respondSomehowNotUsingFetch(event.request))
}
// Even in the case of a request slipping through our isPrivateAddressSpace implementation,
// the mixed content check would still prevent it or any PNA preflight requests from going
// onto the wire.
});
Ok, here's another thought: If we assumed the mixed-content policy wasn't a problem, would service worker then be considered a reasonable solution to the problem? Because if so I don't think it is even necessary to come up with a solution as part of the specification. Once PNA/PermissionDialog is implemented in service workers, the following might be a reasonable application based solution:
// in application.js
// Note that the request is using a secure scheme within the main application context
fetch('https://192.168.0.1')
// Would work equally with HTML elements and other APIs
// <img src="https://192.168.0.1/img.png" />
// in sw.js
addEventListener('fetch', (event) => {
if (needsInsecureRedirection(event.request.url)) {
// Replace the scheme with an insecure scheme and set targetAddressSpace accordingly
return event.respondWith(fetch(makeInsecureScheme(event.request.url), { targetAddressSpace: 'private' } ));
}
});
I recognize that this puts the onus of being able to identify and manage URIs that should be redirected to insecure endpoints onto the application developer, but that doesn't seem too crazy. A simple scheme could be put in place by the application developer to encode that information in the URI itself (e.g. 'https://192.168.0.1?makeInsecure=1') and transform the URI accordingly in the service worker. I still think egress-timing the mixed content check is probably the more comprehensive solution, but from skimming through the fetch, Service Worker and Mixed Content specs for a bit I also recognize that that might not be an exactly trivial undertaking.
In fact this is what I naturally attempted on doing to get PNA/PermissionDialog to work with EventSource in my project, but had to instead go with a fetch()
-based EventSource polyfill when I realized I couldn't send PNA/PermissionDialog fetch()
requests from Service Worker yet.
targetAddressSpace
is made for mixed content check and it seems hard and unworthy to change the current (mixed content spec)[https://www.w3.org/TR/mixed-content/].
Content Security Policy option got some opposition internally because on one hand, we have put too many random stuff into CSP and it is probably not good to do it more, and on the other hand, targetAddressSpace
don't actually meet the CSP policy as it is generally meant to enable a document to restrict the locations of external resources it can load. So we are thinking of alternative way for it.
We would like to propose that websites needs
fetch()
to unlock mixed content fetches in local/private address space.Once
fetch()
is sent withtargetAddressSpace
for a certain domain. It will cached for the current document context and it will be used to enable preflights to the same domain in other contexts, e.g.<iframe>
or<img>
.