Summary
src/lib/crypto/key-manager.js stores the AES-256-GCM storage encryption key as raw Base64 in localStorage. While conversation keys are now encrypted (fix from b769853), the encryption key itself is unprotected.
Impact
Any XSS vulnerability allows an attacker to:
- Read
qryptchat_storage_enc_key from localStorage
- Base64-decode it to get the raw AES-256-GCM key
- Decrypt all conversation keys stored in localStorage
- Read all past and future messages
This is the "bootstrap paradox" of client-side encryption — the key that protects the keys is itself unprotected.
Current Code (key-manager.js ~line 40)
localStorage.setItem(this.storageEncryptionKeyName, Base64.encode(new Uint8Array(exported)));
Recommendation
Use Web Crypto API with extractable: false and store in IndexedDB:
// Generate non-extractable key
this._storageEncKey = await crypto.subtle.generateKey(
{ name: 'AES-GCM', length: 256 },
false, // non-extractable — cannot be read by JS
['encrypt', 'decrypt']
);
// Store handle in IndexedDB (key material never leaves Web Crypto)
await indexedDBManager.storeKey('storage_enc_key', this._storageEncKey);
This way, even if XSS occurs, the attacker cannot extract the raw key bytes. Web Crypto operations work with the key handle but never expose the underlying material.
Severity
Medium — requires XSS as prerequisite, but fully compromises E2E encryption guarantees.
Filed by: eltociear (AI security auditor via ugig.net)
Summary
src/lib/crypto/key-manager.jsstores the AES-256-GCM storage encryption key as raw Base64 inlocalStorage. While conversation keys are now encrypted (fix from b769853), the encryption key itself is unprotected.Impact
Any XSS vulnerability allows an attacker to:
qryptchat_storage_enc_keyfrom localStorageThis is the "bootstrap paradox" of client-side encryption — the key that protects the keys is itself unprotected.
Current Code (key-manager.js ~line 40)
Recommendation
Use Web Crypto API with
extractable: falseand store in IndexedDB:This way, even if XSS occurs, the attacker cannot extract the raw key bytes. Web Crypto operations work with the key handle but never expose the underlying material.
Severity
Medium — requires XSS as prerequisite, but fully compromises E2E encryption guarantees.
Filed by: eltociear (AI security auditor via ugig.net)