The way it works is the server returns a unique service worker script every time, and the script file itself contains an AES key. The user trusts the server not to store this key and the server never sees it again. This AES key is then used to encrypt all persisted local state and sign all cached source files. If the server replaces the service worker, the key is lost and local state cannot be accessed. If the server somehow replaces a source file, its integrity check will fail and the webapp will refuse to load it. If the server manages to skip the service worker and serve a malicious file directly (e.g. because the user did Shift+F5), the malicious file won't have access to any local state because the service worker will refuse to give it access. The server can destroy all local state and then serve a malicious application, but the user will immediately notice, hopefully before interacting with the app, because suddenly all their data is gone.