# Service Worker Security FAQ

[TOC]

This FAQ is specifically about service workers. Also see the [general security
FAQ](faq.md).

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 palmer@chromium.org for a fix.

## Service Workers seem extremely risky! Why are they OK?

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](https://www.w3.org/wiki/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](https://developer.mozilla.org/en-US/docs/Web/HTML/Using_the_application_cache),
which has been available in the OWP for a very long time.

For more background on Service Workers, see [Service Workers
Explained](https://github.com/w3c/ServiceWorker/blob/master/explainer.md).

## Do Service Workers run in a sandbox?

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.

## What APIs can Service Workers access?

The [HTML specification partially enumerates the API surface available to
Workers](https://html.spec.whatwg.org/#apis-available-to-workers). See also
`[Client](https://developer.mozilla.org/en-US/docs/Web/API/Client)`, and
`[ServiceWorkerGlobalScope](https://w3c.github.io/ServiceWorker/#serviceworkerglobalscope-interface)`.
(Note that SWs do not have access to synchronous APIs.)

However, other web platform specifications can add new API surface. For example,
the Permissions API exposes a permissions attribute to workers. Generally, SWs
have access to a subset of the web platform APIs, although there are some
Worker- and Service Worker-specific APIs that do not make sense for in-page
JavaScript.

(`[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.)

## Do Service Workers obey the same-origin policy?

Service Worker registration specifies that [Service Workers must run in the same
origin as their
callers](https://w3c.github.io/ServiceWorker/#register-algorithm).

The origin comparison for finding a Service Worker registration for a request is
[specified](https://w3c.github.io/ServiceWorker/#scope-match-algorithm) 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](https://github.com/w3c/ServiceWorker/issues/1118), but
doesn’t currently seem exploitable.

Only [Secure Contexts can register or use Service
Workers](https://w3c.github.io/webappsec-secure-contexts/#example-c52936fc).

Because SWs can call `importScripts` to import scripts (from any other origin),
it is a good idea for site operators to set a Content-Security-Policy response
header on the ServiceWorker’s JavaScript response, instructing the browser what
sources of script the origin considers trustworthy. That would reduce an XSS
attacker’s ability to pull in their own code.

## Do Service Workers live forever?

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](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API).
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](https://w3c.github.io/ServiceWorker/#dfn-use-cache), 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](https://bugs.chromium.org/p/chromium/issues/detail?id=675540).)

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](https://w3c.github.io/ServiceWorker/#handle-functional-event-algorithm)).

The browser can terminate a running SW thread at almost any time. Chrome
terminates a SW if the SW has been idle for 30 seconds. Chrome also detects
long-running workers and terminates them. It does this if an event takes more
than 5 minutes to settle, or if the worker is busy running synchronous
JavaScript and does not respond to a ping within 30 seconds. When a SW is not
running, Developer Tools and chrome://serviceworker-internals show its status as
STOPPED.

## How can I see Service Workers in Chrome?

You can see them in the **Service Workers** field in the **Application** tab of
**Developer Tools**. You can also look at
[chrome://serviceworker-internals](chrome://serviceworker-internals).

## Do Service Workers keep running after I close the tab?

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](https://cs.chromium.org/chromium/src/chrome/browser/push_messaging/push_messaging_notification_manager.cc?type=cs&l=270),
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](https://gauntface.github.io/simple-push-demo/).)

## Can attackers use Service Workers to trigger attacks developed after SW registration?

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 `<script
src="maybe-v8-payload.js">` as usual, from the in-page JavaScript.

## If a site has an XSS vulnerability, can the attacker permanently compromise that origin for me?

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](https://stackoverflow.com/questions/33986976/how-can-i-remove-a-buggy-service-worker-or-implement-a-kill-switch/38980776#38980776).

In the near future, the right cleanup strategy (for this and other issues) will
be [Clear-Site-Data](https://www.w3.org/TR/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.

## Can sites opt out of Service Workers?

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](https://w3c.github.io/ServiceWorker/#service-worker-script-request).

## How many SWs can an origin, or Chrome itself, spawn?

The current specification and the current implementation in Chrome do not define
any limits.

## Can attackers 'hide' Service Worker scripts in JPEGs or other non-script MIME types?

Can an attacker upload (for example) JPEG files to a site that supports the
capability, and then use the uploaded files as SW scripts?

The SW specification and implementation require that a SW script have the right
JavaScript MIME type. (Additionally, as noted elsewhere in this document, server
operators should reject SW script requests except for the exact endopints they
intend to serve SW scripts from.)

## Can iframes register Service Workers?

Yes, if and only if they are themselves secure contexts. [By
definition](https://w3c.github.io/webappsec-secure-contexts/#examples-framed),
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.)

## Why doesn’t Chrome prompt the user before registering a Service Worker?

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](https://en.wikipedia.org/wiki/Gears_(software)) also do not/did not
prompt the user.)

[An informal study by Chrome team members Rebecca Rolfe, Ben Wells, and Raymes
Khoury](https://docs.google.com/presentation/d/1suzMhtvMtA11jxPUdH1jL1oPh-82rTymCnslgR3ehEE/edit#slide=id.p)
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.

## What if I don't want *any* SWs?

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:

1. Visit https://gauntface.github.io/simple-push-demo/
1. 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
1. In a third tab, go to chrome://settings/clearBrowserData to clear browsing data;
   clear it by clicking **Clear browsing data**
1. Reload chrome://serviceworker-internals/ to see that the SW's status is now
   REDUNDANT and STOPPED
1. Close the Simple Push Demo tab
1. Reload chrome://serviceworker-internals/ to see that the SW is now gone

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](https://paul.kinlan.me/slice-the-web/).
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](https://www.w3.org/2001/tag/), [W3C’s Web
Platform Incubator Community Group](https://www.w3.org/blog/2015/07/wicg/), and
[blink-dev@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/blink-dev).
Security and privacy reviews are part of the process and we invite knowledgeable
experts to participate in those open fora.

## What are some SW best practices for site operators?

*    [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).

## What SW bugs would quality for a bounty under [Chrome’s VRP](https://www.google.com/about/appsecurity/chrome-rewards/index.html)?

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](https://bugs.chromium.org/p/chromium/issues/list?can=1&q=Type%3DBug-Security+serviceworker&colspec=ID+Pri+M+Stars+ReleaseBlock+Component+Status+Owner+Summary+OS+Modified&x=m&y=releaseblock&cells=ids)
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](https://bugs.chromium.org/p/chromium/issues/entry?template=Security%20Bug).
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](https://bugs.chromium.org/p/chromium/issues/entry?template=Security%20Bug).
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!
