-
Notifications
You must be signed in to change notification settings - Fork 315
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
Is it possible to serve service workers from CDN/remote origin? #940
Comments
I don't think this is actually ambiguous in the spec. In step 2 of the Register algorithm we check to make sure that the origin of the (resolved) script URL is the same as the origin of the job's referrer (which more or less is the document that called register). And since we also compare the scope to be same origin with that, that means that the document registering the service worker, the scope of said service worker, and the main script of the service worker all have to be same origin. You could have your main script (on the same origin as your website) be nothing but an importScripts('https://cdn.example.com/...') though. Currently that has the downside that changes in imported scripts are not taken into account when deciding if a new version of a service worker should be downloaded, but we're changing/fixing that to treat imported scripts the same as the main script for update checks (#839). |
Are there security reasons for not being able to load a service worker from a remote origin? |
Yes, it would give a remote origin control over your origin. |
Yeah, we're not doing this as it turns a small XSS into a huge long-term issue. If we allowed something like this, the controlled origin would need to opt into it somehow, maybe via something like CSP. It seems like |
Just to play devil's advocate, what is the material difference between a cross-origin top level script and a top level script with a single cross-origin importScripts()? |
You can change the latter but not the former. |
Is there a way to bypass this error locally by using some sort of "unsafely-treat-insecure-origin*" flag? |
No, the main service worker resource must be same-origin. |
Are there any plans to allow this in the future? The security could be retained by requiring a hash-code for cross-origin serviceworker registrations. |
I don't see how that solves the security issues. |
If the browser only accepts a serviceworker with the exact same hash-code I provided, there is no xss-risk imo? In my case I have a domain where I store my (almost) static resources which are shared/used at several other domains. It would be very beneficial to be able to also store the serviceworker on that domain. |
The XSS attacker can compute the hash of the resource hosted off-domain, so the hash gives no extra defense. |
He could indeed compute the hash, but I don't see how that could be an attack vector. It's not that the hash is supposed to be hidden. Can you explain what he could do with the hash and how that could possibly tamper the requested resource? |
Sorry, my comment was rather unhelpful. An attacker using an XSS exploit on example.com to register a serviceworker hosted at evil.net by injecting script can just as easily register the serviceworker including a hash in the registration script. Therefore the hash adds no mitigation. Perhaps you're not understanding the core XSS problem. It presumes that example.com has an exploit which allows someone to alter the content served by example.com in such a way that arbitrary script is executed. Combined with the ability to register a service worker, this would allow a hacker to cause a service worker to be registered that then intercepts all future loads of example.com content. If the service worker is loaded from evil.com then evil.com now has full control of all content loaded by pages from example.com. The same-origin restriction mitigates this by only allowing scripts hosted at example.com to be registered as a service worker; the worst the XSS exploiter can do is register content under the control of example.com - and badness is possible by abusing existing content within the limits of other mitigations - but in the worst case example.com can replace the content to get back control. Once this threat (XSS leading to persistent intercept) and mitigation (same-origin requirement) is understood, it should be clearer why the hash is an insufficient replacement mitigation. |
Thank you for the clear explanation, I now see the real threat. |
This seems to be in violation of the purpose of the Aren't the two incompatible as it is right now? (Incompatible in that if the same-origin policy takes precedence over |
That feedback is better addressed at https://github.com/w3c/webappsec-csp, but I'll note that |
@annevk I might be misunderstanding, but I believe the trouble really lies with the ServiceWorker spec, in that it mostly makes Currently, the |
There's various reasons why cross-origin (service) workers aren't workable as already explained earlier. And no, CSP isn't meant to enable things, it only allows for adding further restrictions. |
Sorry for my misunderstading of CSP – I saw some behavior in Chrome that I interpreted as CSP allowing to extend what was allowed. Then, I have just once last pushback. I can agree that ServiceWorker need heavy restrictions, but what is the rationale for a standard "background" web worker to be same-origin? |
Similar to documents, we use the URL of the worker to determine the service worker to use (especially important for shared workers as you might imagine). That wouldn't work cross-origin. They also create their own global object and such, and it would be slightly weird if the origin of that wasn't obtained from the request URL, but from the entity creating the worker. |
Thank you! – also found the rationale over here: whatwg/html#3109 (comment) I still think that non-shared, non-service workers should have different behavior. The same-origin restriction will prevent adoption of workers for reasonable use-cases e.g. PDF.js hosted on a CDN 🙁 |
You can use a |
I also believe the implementation has to be changed to allow for serviceworkers to be hosted on CDN's. |
So outside the presumption of an already existing vulnerability, are you thus saying that the hash can provide some meaningful leverage with respect to loading sw files from different domains? @inexorabletash |
The hash is not safe either. If the file is hosted on their domain, there is nothing I can do to prevent them sending notifications to my users (the already subscribed ones) using my own domain. |
Maybe you can put a service worker script on your domain, and let it |
@Menci or just use |
@jakearchibald : is possible that google cache my service worker if i am using amp and amp-signed-exchange ? |
Hi @jakearchibald I had one doubt. I am able to serve this sw.js file through nginx server but when I try to use importScripts() it throws error-> self.importScripts() is not a function any idea what is the workaround for this? |
I'm happy to debug a running version of this. |
Applications can provide their own `SW_SCRIPT`, which depends on, for instance: `APP_BASE_HREF`. Since the `deployUrl` was deprecated you need to use for CDN the `appBaseHref` and for the routing the `APP_BASE_HREF`. The service worker can't be initialized in a browser from a different url; therefore you need to hardcode the current origin: `ServiceWorkerModule.register('https://example.com/ngsw-worker.js')`. Another problem if a site works on two different domains. Related links: * w3c/ServiceWorker#940
Hey all,
I want to serve a service worker from a CDN, but I can't figure out how to get that to work.
I expected this to work:
But it throws the following error in Chrome:
With the current wording, it seems like Service-Worker-Allowed allows loading the service worker from a remote origin.
https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-allowed
However, all of the examples and discussion only use Service-Worker-Allowed with relative URLs.
Digging through the Chromium code, I'm pretty sure the error is thrown before the request is made to the url, which means it's made before we can check the header on the sw response:
https://cs.chromium.org/chromium/src/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp?q=%22does+not+match+the+current+origin%22&sq=package:chromium&dr=C&l=224
You can follow the rabbit hole down 'canRequest', but I'm pretty sure nothing in that function allows you to allow remote scripts dynamically (e.g. with a header).
Questions:
Thanks for your time! BTW, you all have done excellent work with the spec.
The text was updated successfully, but these errors were encountered: