]> git.codecow.com Git - libnemo.git/commitdiff
Refactor vault secret parsing and zero out local copies on error.
authorChris Duncan <chris@codecow.com>
Wed, 5 Aug 2026 06:34:53 +0000 (23:34 -0700)
committerChris Duncan <chris@codecow.com>
Wed, 5 Aug 2026 06:34:53 +0000 (23:34 -0700)
src/lib/vault/parsers.ts

index ce333fe65d67756a6157dfdaad4f15cc35e781da..34d497013250c671ac821f18df6219879340170b 100644 (file)
@@ -30,6 +30,9 @@ export function parseAction (data: Record<string, unknown>) {
  * Parse inbound message from main thread to worker into typechecked variables.
  */
 export function parseData (action: string, data: Record<string, unknown>) {
+       let seed: ArrayBuffer | undefined
+       let encrypted: ArrayBuffer | undefined
+       let message: ArrayBuffer | undefined
        try {
                // Import requires seed or mnemonic phrase
                if (action === 'load' && data.seed == null && data.mnemonicPhrase == null) {
@@ -37,16 +40,17 @@ export function parseData (action: string, data: Record<string, unknown>) {
                }
 
                // Seed to load
-               if (action === 'load' && 'seed' in data && !(data.seed instanceof ArrayBuffer)) {
-                       throw new TypeError('Seed required to load wallet')
-               }
-               const seed = data.seed instanceof ArrayBuffer
-                       ? data.seed.slice()
-                       : undefined
-               if (data.seed instanceof ArrayBuffer) {
-                       new Uint8Array(data.seed).fill(0)
-                       delete data.seed
+               if (action === 'load') {
+                       if (!('seed' in data) {
+                               throw new TypeError('Seed required to load wallet')
+                       }
+                       if (!(data.seed instanceof ArrayBuffer)) {
+                               throw new TypeError('Invalid wallet seed')
+                       }
+                       seed = data.seed.slice()
                }
+               new Uint8Array(data.seed).fill(0)
+               delete data.seed
 
                // Mnemonic phrase to load
                if (action === 'load' && 'mnemonicPhrase' in data && typeof data.mnemonicPhrase !== 'string') {
@@ -74,14 +78,10 @@ export function parseData (action: string, data: Record<string, unknown>) {
                        if (!(data.encrypted instanceof ArrayBuffer)) {
                                throw new TypeError('Invalid wallet encrypted secrets')
                        }
-               }
-               const encrypted = data.encrypted instanceof ArrayBuffer
-                       ? data.encrypted.slice()
-                       : undefined
-               if (data.encrypted instanceof ArrayBuffer) {
-                       new Uint8Array(data.encrypted).fill(0)
-                       delete data.encrypted
-               }
+                       encrypted = data.encrypted.slice()
+               }       
+               new Uint8Array(data.encrypted).fill(0)
+               delete data.encrypted
 
                // Index for child account to derive or sign
                if ((action === 'derive' || action === 'sign') && typeof data.index !== 'number') {
@@ -99,10 +99,9 @@ export function parseData (action: string, data: Record<string, unknown>) {
                        if (!(data.message instanceof ArrayBuffer)) {
                                throw new TypeError('Invalid data to sign')
                        }
+                       message = data.message.slice()
                }
-               const message = data.message instanceof ArrayBuffer
-                       ? data.message
-                       : undefined
+               new Uint8Array(data.message).fill(0)
                delete data.message
 
                // Vault configuration
@@ -120,6 +119,9 @@ export function parseData (action: string, data: Record<string, unknown>) {
 
                return { seed, mnemonicPhrase, mnemonicSalt, encrypted, index, message, timeout }
        } catch (err) {
+               new Uint8Array(seed).fill(0)
+               new Uint8Array(encrypted).fill(0)
+               new Uint8Array(message).fill(0)
                console.error(err)
                throw new Error('Failed to extract data', { cause: err })
        }