Take a look at QmaEtDG87K69mVR7sc48DemHpj3LqxKaQfDw6qJr2AGbmZ:
<!doctype html>
<script>
navigator.serviceWorker.register('/ipfs/QmRcqyy8yFsVhgErobYrTcF5PSQHC36TqpA19xnBkQpFcB');
</script>
The requested ServiceWorker file is the following:
self.oninstall = event => event.waitUntil(self.skipWaiting());
self.onactivate = event => event.waitUntil(self.clients.claim());
self.onfetch = event => event.respondWith(new Response('All my base are belong to us.'));
This currently does not work for only one reason: The Content-Type on the ServiceWorker file is
not application/javascript but text/plain. If it was set to application/javascript, I could
do the following:
gateway.ipfs.io endpoint would receive the same response.Currently, the Go FileServer implementation, which the gateway uses, does not sniff JavaScript to set a Content-Type: application/javascript header. If they ever change that, or IPFS exposes control over Content-Type, the gateway would become vulnerable to the attack above.
I think ServiceWorker are powerful and they should be allowed on IPFS. ServiceWorker are scoped to
the path where the ServiceWorker file is located. Most of the time it would be located at paths
like /ipfs/<HostID>/serviceworker.js, and therefore be in control of all requests to /ipfs/<HostID>/... which is entirely reasonable.
There’s currently no way to completely disable ServiceWorker for a domain or a path, so I created an issue on the ServiceWorker spec. For the time being, my suggestion is to sett the header Service-Worker-Allowed: /_jail on all requests that match ^/ip[fn]s/[^/]+$ on the gatway.
Hah, very interesting. Thanks for the detective work here :)
We will definitely keep this in mind when moving forward with service worker addons
Thanks for converting the report into this issue and for opening https://github.com/w3c/ServiceWorker/issues/1165 as a proposal!
Putting this on the 0.4.12 milestone so we give it more attention. I know we want to start doing more with service workers and content types, so its important to keep this in mind and follow up.
Happy to help review any idea y’all have in the general area of Service Worker :)
Solution would be to block requests to /ipfs/Qm...AAA with Service-Worker: script header.
Requests to /ipfs/Qm...AAA/xxxx.js should be allowed.
See https://github.com/w3c/ServiceWorker/issues/1165#issuecomment-341688472
I like that solution.
Just for clarification for anyone who is new to Service Workers (me), I was initially confused as to why SWs path scope rules wouldn't solve this, but I see now that it doesn't
If you register a SW from:
/ipfs/QmHash/sw.js
then the scopeUrl is /ipfs/QmHash/ and your SW can only manipulate requests for resources below that hash, which is good and proper. But if as in the example you register a SW directly from:
/ipfs/QmHash
and the gateway starts to serve files like that with the correct js mime-type where appropriate, then the browser will have loaded a js file called QmRcqyy8yFsVhgErobYrTcF5PSQHC36TqpA19xnBkQpFcB from the path /ipfs.
In ServiceWorker terms, the scopeUrl ends up being /ipfs/, and that means all other requests for files served from the gateway end up under the control of a potentially malicious ServiceWorkers control.
Of note, path based scopes for service workers were, at least partly, introduced to allow usecases where a service hosts content from multiple users in sibling directories, see: https://github.com/w3c/ServiceWorker/issues/468
Also of note there is an active issue discussing the service worker path scope trailing slash issue and sub origins here: https://github.com/w3c/ServiceWorker/issues/1272
Just for the record, another vector for this could be future support for returning content-type stored in "Extended Attributes" of https://github.com/ipfs/unixfs-v2/issues/11
Most helpful comment
Just for clarification for anyone who is new to Service Workers (me), I was initially confused as to why SWs path scope rules wouldn't solve this, but I see now that it doesn't
If you register a SW from:
then the scopeUrl is
/ipfs/QmHash/and your SW can only manipulate requests for resources below that hash, which is good and proper. But if as in the example you register a SW directly from:and the gateway starts to serve files like that with the correct js mime-type where appropriate, then the browser will have loaded a js file called
QmRcqyy8yFsVhgErobYrTcF5PSQHC36TqpA19xnBkQpFcBfrom the path/ipfs.In ServiceWorker terms, the scopeUrl ends up being
/ipfs/, and that means all other requests for files served from the gateway end up under the control of a potentially malicious ServiceWorkers control.Of note, path based scopes for service workers were, at least partly, introduced to allow usecases where a service hosts content from multiple users in sibling directories, see: https://github.com/w3c/ServiceWorker/issues/468
Also of note there is an active issue discussing the service worker path scope trailing slash issue and sub origins here: https://github.com/w3c/ServiceWorker/issues/1272