W3C home > Mailing lists > Public > public-webappsec@w3.org > September 2017

Using Service Workers to improve the security model of the web

From: Daniel Huigens <d.huigens@gmail.com>
Date: Thu, 21 Sep 2017 01:12:56 +0200
Message-ID: <CAL14OeHKeHX8BVSbHG_1rPNvZ4h49_uVo5x0CRsVVMs4fafH+Q@mail.gmail.com>
To: public-webapps@w3.org
Cc: public-webappsec <public-webappsec@w3.org>, public-web-security@w3.org
Hi all,

A short while back I wrote a blog post [1] on using Service Workers to mitigate
the "Javascript Trust Problem" of client-side crypto [2], which is that the
client trusts the server every time it opens a web app, and client-side crypto
therefore can't protect from the server much. (Previously discussed at [3] and
[4].) By installing a Service Worker, which sits between the client and server
and verifies the integrity of all (updated) source code, we can improve that to
Trust On First Use.

This allows us, for example, to make it impossible to compromise the Javascript
of a web app for existing users when the server gets hacked, by requiring, in
the Service Worker, that all code be signed with a given public key. This is
necessary for a web app that client-side encrypts data and doesn't trust the
server. (I can elaborate on threat and security model if you want, I wanted to
keep a modicum of brevity.)


Now, some of you are probably yelling, "But Service Worker lifecycle!"
Indeed, Service Workers have been carefully designed to update on every page
load, and the old Service Worker can't prevent a compromised, new Service Worker
to be installed, for a good reason. It's not necessary to change that. However,
it would be nice to be able to read the code of the new Service Worker in the
old Service Worker, in the updatefound event. Then, if that new code doesn't
match the signature, we can show a big fat warning and the user can choose (for
example) not to enter their password.

One option is to allow the old Service Worker to request the new Service Worker
file from cache with fetch('/service-worker.js', {cache: 'only-if-cached'}).
However, if the new Service Worker calls skipWaiting(), that request currently
gets canceled. To solve that, we could make updatefound an ExtendableEvent.
Furthermore, Firefox seems to have a separate cache for Service Worker files.

Another option is a dedicated property or function, like
registration.installing.scriptBody or updatefoundevent.newSource.
(Although it would still be nice to make updatefound an ExtendableEvent, to
allow the Service Worker to fetch a public key from somewhere, for example.)

Let me know what you think!

Best wishes,
Daniel Huigens


[1] http://blog.airbornos.com/post/2017/08/03/Transparent-Web-Apps-using-Service-Worker
[2] https://tonyarcieri.com/whats-wrong-with-webcrypto#the-ugly-we39re-still-in-a-browser_1
[3] https://lists.w3.org/Archives/Public/public-web-security/2014Sep/0006.html
[4] https://lists.w3.org/Archives/Public/public-webappsec/2017Apr/0042.html
Received on Wednesday, 20 September 2017 23:13:40 UTC

This archive was generated by hypermail 2.3.1 : Monday, 23 October 2017 14:54:23 UTC