Service Worker Security FAQ
This FAQ is specifically about service workers. Also see the general security FAQ.
Like the general security FAQ, this document is a collaborative effort by many Chromium developers. (rsesek, estark, falken, slightlyoff, jakearchibald, evn, raymes, ainslie, mek, lgarron, elawrence, kinuko, palmer, your name here...) Last updated 12 May 2017. If you see an error or have an additional question, and have a Chromium account, go ahead and fix it. If you don't have a Chromium account, email firstname.lastname@example.org for a fix.
Service Workers (SW) are indeed powerful. They support compelling web applications that can run offline or with intermittent connectivity. You can edit documents, browse and buy from catalogs, send social media messages, write email, etc. even in the subway! Service Workers can make the web platform more viable than ever before, enabling web apps to better compete with native apps even while essentially retaining the browse-to-use, sandboxed nature of the Open Web Platform (OWP) that we all love. The rest of this FAQ will explain how the SW designers and implementers have mitigated the risks that necessarily come with this functionality.
Service Workers are a replacement for and an improvement on the legacy Application Cache API, which has been available in the OWP for a very long time.
For more background on Service Workers, see Service Workers Explained.
Yes, SWs run in renderer processes. When Chrome starts a SW, it chooses a renderer process that is associated with the SW’s origin. If one does not exist, the browser creates a new one using a new SiteInstance for the origin.
The HTML specification partially enumerates the API surface available to Workers. See also Client, and ServiceWorkerGlobalScope. (Note that SWs do not have access to synchronous APIs.)
([Service]WorkerGlobalScope is of course not necessarily a strict subset of Window, and similarly WorkerNavigator is not necessarily a strict subset of Navigator. And the various SW events are of course only exposed to SWs.)
Service Worker registration specifies that Service Workers must run in the same origin as their callers.
The origin comparison for finding a Service Worker registration for a request is specified to be to be a longest-prefix match of serialized URLs, including their path. (E.g. https://example.com/ != https://example.com.evil.com/.) This specification gap seems fragile to us, and should be fixed to be specified and implemented as actual origin equality, but doesn’t currently seem exploitable.
There are two concepts of “live” here. One is about the installed registration and one is about the running Service Worker thread.
The installed registration lasts indefinitely, similar to origin-scoped storage like IndexedDB. Additionally, the browser performs an update check after any navigation using the Service Worker, invalidating the HTTP cache every 24 hours. (Additionally, according to a recent spec change, browsers will revalidate the HTTP cache for SW scripts unless the site opts into using the cache. Chrome does not yet adhere to this new part of the spec, but will soon.)
The browser also performs an update check whenever the SW starts and periodically while the worker is running, if it has not checked in the last 24 hours (86,400 seconds, as specified in the Handle Functional Event algorithm).
You can see them in the Service Workers field in the Application tab of Developer Tools. You can also look at chrome://serviceworker-internals.
If an origin has any Service Workers running, each worker will be shut down soon after it processes the last event. Events that can keep a worker alive include push notifications. (Note that the push notifications will trigger a user-visible notification if the SW does not create one, and they also require the person to grant the origin permission in a prompt. you can see that in action in this push notifications demo app.)
For example, could an attacker convince users to visit a malicious website, then wait for (e.g.) a V8 bug to show up in Chrome's repository, then write an exploit, and then somehow run that exploit on the machines of everyone who visited the malicious website in the last month or so?
Without explicit permission from the user, the browser won't let the SW poll for/receive any push notification events the attacker's server may (try to) send, and hence the SW won't get a chance to handle the events.
However, if/when Foreign Fetch ships, the situation will change if people browse sites that fetch resources from the attacker's server.
An XSS attacker can indeed register an evil SW. As before SWs, XSS is a very powerful mode of attack on a web origin. To mitigate the risk that an XSS attack will register a malicious SW, the browser requires that the SW registration URL come from the origin itself. Thus, to use an XSS attack to register a malicious SW, the attacker needs the additional capability to host their own scripts on the server.
Here is another exploit scenario: If the page with an XSS vulnerability also has a JSONP endpoint, the attacker could use it to (1) bypass CSP; (2) register a SW; and (3) call importScripts to import a third-party script to persist until
the site operators detect and remediates the issue, and users navigate to the site again while online.
In an XSS situation, the 24 hour cache directive limit ensures that a malicious or compromised SW will outlive a fix to the XSS vulnerability by a maximum of 24 hours (assuming the client is online). Site operators can shrink the window of vulnerability by setting lower TTLs on SW scripts. We also encourage developers to build a kill-switch SW.
In the near future, the right cleanup strategy (for this and other issues) will be Clear-Site-Data.
Additionally, site operators should ignore (e.g. respond with 400 Bad Request) requests that have the Service-Worker request header for domains or paths that the server doesn’t expect to be serving SW scripts for.
Sites that do not intend to serve Service Workers on particular domains or paths can check for and explicitly reject requests for worker scripts, by checking for the Service-Worker request header.
The current specification and the current implementation in Chrome do not define any limits.
Yes, if and only if they are themselves secure contexts. By definition, that means that they must be nested inside secure contexts, all the way up to the top-level document.
Additionally, third-party iframes can’t register Service Workers if third party cookies are blocked. (See chrome://settings/content.)
The Chrome Team generally prefers to ask people about things that are privacy-relevant, using nouns and verbs that are simple and precise (camera, mic, geo-location, and so on). But we avoid asking questions about resource-use (caching, persistence, CPU, and so on). We’re better prepared to make those types of resource decisions automatically. (Consider, for example, that the HTTP cache, AppCache, and even Google Gears also do not/did not prompt the user.)
An informal study by Chrome team members Rebecca Rolfe, Ben Wells, and Raymes Khoury suggests that people do not generally have sufficient context to understand permission requests triggered by API calls from origins in iframes. It seems reasonable that people would similarly lack the context to understand requests from Service Workers.
You can disable SWs by disabling storage in chrome://settings. SW are gated on cookie/local data storage settings. (That is, the Block sites from setting any data radio button in Content Settings.)
Clearing browser data (CBD; the Clear browsing data... button in Settings or chrome://settings/clearBrowserData) also deletes SWs. You can verify that by following this test procedure:
- Visit https://gauntface.github.io/simple-push-demo/
- In a second tab, visit chrome://serviceworker-internals/ to see the
ACTIVATED and RUNNING SW
- Note that the origin/the origin's SW cannot actually send any push notifications until you grant it that permission
- In a third tab, go to chrome://settings/clearBrowserData to clear browsing data; clear it by clicking Clear browsing data
- Reload chrome://serviceworker-internals/ to see that the SW's status is now REDUNDANT and STOPPED
- Close the Simple Push Demo tab
- Reload chrome://serviceworker-internals/ to see that the SW is now gone
You can also remove individual SW registrations with chrome://serviceworker-internals/.
If you really want to not use the modern web, you can use one of the browsers that don't (yet) support SWs. But, eventually, the Open Web Platform will continue to evolve into a powerful, useful platform supporting applications that are secure, linkable, indexable, composable, and ephemeral. Yes, SWs make web apps somewhat less ephemeral, but we believe the increased applicability of the OWP is worth it.
Browser vendors are committed to ensuring the security of the OWP improves even as we give it new capabilities. This process happens in the open, in fora like W3C Technical Architecture Group, W3C’s Web Platform Incubator Community Group, and email@example.com. Security and privacy reviews are part of the process and we invite knowledgeable experts to participate in those open fora.
[Build a kill-switch SW](https://stackoverflow.com/questions/33986976/how-can-i-remove-a-buggy-service-worker-or-implement-a-kill-switch/38980776#38980776). Use [Clear-Site-Data](https://www.w3.org/TR/clear-site-data/) when it becomes available. Be aware of the need for longer session lifetimes, since clients may go offline and SWs might need to POST cached requests after coming back online. [Here is one way to handle that](https://developers.google.com/web/updates/2016/06/2-cookie-handoff).
If you could break one or more of the security assertions we make in this FAQ, that would be potentially rewardable under the Vulnerability Rewards Program (VRP). Here is a non-exhaustive list of examples:
Over-long registration/lifetime (e.g. a SW able to run or stay alive even without incoming events to handle) Same-origin bypass or off-origin SW registration Access to APIs that require prompts, choosers, or permissions, without permission having been granted to the origin Geolocation Hardware sensors Microphone, camera, media devices USB, Bluetooth
Here is a list of historical SW security bugs in Chromium’s bug tracker.
If you believe you have found a bug in the SW specification, please file a new Chromium bug using the Security template. It’s a good idea to file bugs with all browser vendors that implement the buggy section of the spec.
If you believe you have found a bug in Chrome’s implementation of SW, please file a new bug using the Security template. The Chrome Security Team will triage it within 1 or 2 business days. Good bug reports come with minimal test cases that demonstrate the problem!