]> git.codecow.com Git - libnemo.git/commitdiff
Zero out sensitive data in worker from input message as it is processed.
authorChris Duncan <chris@zoso.dev>
Sat, 9 Aug 2025 08:16:01 +0000 (01:16 -0700)
committerChris Duncan <chris@zoso.dev>
Sat, 9 Aug 2025 08:16:01 +0000 (01:16 -0700)
src/lib/wallet/safe.ts

index c39b9b670ccd0bf46e35b6e35248c9dbe0967704..3f9305111d452ef2302eda0880d16feec845b982 100644 (file)
@@ -401,7 +401,11 @@ export class Safe {
                if (messageData.password != null && !(messageData.password instanceof ArrayBuffer)) {
                        throw new TypeError('Password must be ArrayBuffer')
                }
-               const password = messageData.password
+               let password = messageData.password?.slice()
+               if (messageData.password instanceof ArrayBuffer) {
+                       new Uint8Array(messageData.password).fill(0)
+                       delete messageData.password
+               }
 
                // IV for crypto key, included if unlocking or generated if creating
                if (action === 'unlock' && !(messageData.iv instanceof ArrayBuffer)) {
@@ -423,6 +427,10 @@ export class Safe {
                const key = password instanceof ArrayBuffer
                        ? await this.#createAesKey(action === 'unlock' ? 'decrypt' : 'encrypt', password, keySalt)
                        : undefined
+               if (password instanceof ArrayBuffer && !password.detached) {
+                       new Uint8Array(password).fill(0)
+                       password = undefined
+               }
 
                // Type of wallet
                if (messageData.type !== undefined && messageData.type !== 'BIP-44' && messageData.type !== 'BLAKE2b') {
@@ -436,12 +444,16 @@ export class Safe {
                }
 
                // Seed to import
-               if (action === 'import' && 'seed' in message && !(messageData.seed instanceof ArrayBuffer)) {
+               if (action === 'import' && 'seed' in messageData && !(messageData.seed instanceof ArrayBuffer)) {
                        throw new TypeError('Seed required to import wallet')
                }
                const seed = messageData.seed instanceof ArrayBuffer
-                       ? messageData.seed
+                       ? messageData.seed.slice()
                        : undefined
+               if (messageData.seed instanceof ArrayBuffer) {
+                       new Uint8Array(messageData.seed).fill(0)
+                       delete messageData.seed
+               }
 
                // Mnemonic phrase to import
                if (action === 'import' && 'mnemonicPhrase' in message && typeof messageData.mnemonicPhrase !== 'string') {
@@ -450,6 +462,7 @@ export class Safe {
                const mnemonicPhrase = typeof messageData.mnemonicPhrase === 'string'
                        ? messageData.mnemonicPhrase
                        : undefined
+               delete messageData.mnemonicPhrase
 
                // Mnemonic salt for mnemonic phrase to import
                if (action === 'import' && messageData.mnemonicSalt != undefined && typeof messageData.mnemonicSalt !== 'string') {
@@ -458,6 +471,7 @@ export class Safe {
                const mnemonicSalt = typeof messageData.mnemonicSalt === 'string'
                        ? messageData.mnemonicSalt
                        : undefined
+               delete messageData.mnemonicSalt
 
                // Encrypted seed and possibly mnemonic
                if (action === 'unlock') {
@@ -469,8 +483,12 @@ export class Safe {
                        }
                }
                const encrypted = messageData.encrypted instanceof ArrayBuffer
-                       ? messageData.encrypted
+                       ? messageData.encrypted.slice()
                        : undefined
+               if (messageData.encrypted instanceof ArrayBuffer) {
+                       new Uint8Array(messageData.encrypted).fill(0)
+                       delete messageData.encrypted
+               }
 
                // Index for child account to derive or sign
                if ((action === 'derive' || action === 'sign') && typeof messageData.index !== 'number') {
@@ -492,6 +510,7 @@ export class Safe {
                const data = messageData.data instanceof ArrayBuffer
                        ? messageData.data
                        : undefined
+               delete messageData.data
 
                return { action, type, key, iv, keySalt, seed, mnemonicPhrase, mnemonicSalt, encrypted, index, data }
        }