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 email@example.com 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
[ServiceWorkerGlobalScope](https://w3c.github.io/ServiceWorker/#serviceworkerglobalscope-interface). (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.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.
Because SWs can call
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.
Similarly, you might imagine a SW that tries to use
importScripts to periodically (re-)load
maybe-v8-payload.js. But, the SW would only get to do that as part of an event handler. And if the SW isn‘t getting any events (because the person is not browsing or navigating to attacker.com, and because the person never granted attacker.com push notification permission), then it will never get to run its event handlers, and so again the SW won’t get a chance to attack.
If the person is currently browsing attacker.com, then the attacker doesn't gain any additional attack benefit from a Service Worker. They can just
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
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.
Can an attacker upload (for example) JPEG files to a site that supports the capability, and then use the uploaded files as SW scripts?
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:
You can also remove individual SW registrations with chrome://serviceworker-internals/.
Another way to avid SWs is to 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 firstname.lastname@example.org. Security and privacy reviews are part of the process and we invite knowledgeable experts to participate in those open fora.
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:
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!