Prompt and setting
The app encrypts local data in the browser and needs a key across sessions. The design should reduce key exposure, but it must state limits: code running in the origin can still invoke permitted operations and users can lose recoverability.
What the interviewer tests
- Understanding secure contexts, CryptoKey extractability, and key usages.
- Separating encrypted data storage from key recovery and threat modeling.
- Explaining why browser cryptography does not make XSS harmless.
Clarifying questions before answering
- Is the threat a stolen storage record, a passive attacker, or active same-origin script?
- Must data survive logout, device loss, password reset, and browser profile deletion?
- Can a user-supplied passphrase or WebAuthn credential unlock a wrapping key?
- Which algorithms, key usages, browser support, and migration paths are required?
30-second answer framework
I would require HTTPS, generate or import a CryptoKey with extractable set to false and only the needed usages, and store the key handle in IndexedDB rather than exporting raw key bytes. Ciphertext, nonce, algorithm parameters, and version stay separate from the key. I would pair this with CSP, strict dependency controls, and a recovery plan, while stating that active same-origin script can still call encryption APIs or read plaintext when the app is open.
Step-by-step deep dive
1. Define the threat model
Non-extractability limits accidental export and many storage-theft paths. It does not stop an attacker who executes script in the origin from asking the app to decrypt data or reading plaintext in memory. State that boundary before promising security.
2. Create or import the key
Use a supported algorithm and purpose-specific usages such as encrypt and decrypt. Generate the key in a secure context or import wrapped material with the desired extractability flag. Reject unexpected algorithm parameters and avoid storing raw key material in local storage.
3. Persist ciphertext safely
Store ciphertext, a fresh nonce per encryption, authenticated metadata, key version, and schema version. Use authenticated encryption such as AES-GCM with unique nonces under one key. Keep tenant or user scope in associated data, not as an implicit trust decision.
4. Plan recovery and rotation
A non-extractable key can become unusable after profile deletion or device loss. Offer a deliberate recovery path, for example a passphrase-derived wrapping key or a server-mediated re-encryption flow, without silently downgrading to plaintext. Version keys and migrate records transactionally.
5. Test and operate
Test unsupported algorithms, insecure contexts, quota errors, interrupted writes, nonce reuse, version migration, logout, and recovery failure. Apply CSP and dependency review, avoid sensitive logs, and measure decryption failures without recording plaintext.
High-quality sample answer
“I would require HTTPS, generate a purpose-limited CryptoKey with extractable false, and persist only its browser-managed handle in IndexedDB. Each record stores ciphertext, a unique nonce, authenticated metadata, and key version. I would define recovery before shipping because profile loss can make a non-extractable key unrecoverable. CSP and dependency controls reduce active-script risk, but an XSS payload running in the origin may still invoke allowed decrypt operations or read plaintext while the app is open.”
Common mistakes
- Store the raw key in localStorage → storage theft exposes plaintext access → persist a non-extractable key handle.
- Reuse a nonce with AES-GCM → confidentiality and integrity can fail → generate a unique nonce per key and record.
- Claim XSS is solved → same-origin code can use the app’s authority → state the active-script limit.
- Skip recovery design → profile loss destroys data access → define wrapping, reset, and migration flows.
Follow-up questions and responses
Does IndexedDB make the key safe from XSS?
No. It avoids placing raw bytes in a simple storage API, but same-origin script may access the database or call application code. Use CSP, trusted dependencies, and a realistic threat model.
How can a user recover after device loss?
Wrap a data key with a key derived from a user-held secret or a recovery credential, or re-encrypt through an authenticated server flow. Explain offline and reset trade-offs; never silently create a new key that cannot decrypt old data.
Can the key be exported during rotation?
Only if the policy permits it. Prefer generating a new key and re-encrypting records while both versions are available; if wrapping is required, protect the wrapping key and audit the transition.