Skip to content

fix(crypto): erase intermediate password bytes in v1 KDF input builder - #162

Merged
404SecNotFound merged 1 commit into
mainfrom
claude/codebase-review-issues-4vhh68
Sep 4, 2026
Merged

fix(crypto): erase intermediate password bytes in v1 KDF input builder#162
404SecNotFound merged 1 commit into
mainfrom
claude/codebase-review-issues-4vhh68

Conversation

@404SecNotFound

Copy link
Copy Markdown
Owner

What

buildBaseMaterial (src/lib/keymaker-crypto.ts) builds the v1 KDF input from the NFC-normalized password and an optional key file. It left a second, unzeroed copy of the password in memory:

  • No-key-file path: it encoded the password into passwordBytes, then copied those bytes into a fresh buffer and returned the copy. The caller erases the returned buffer, but the original passwordBytes was never zeroed, so a second copy of the password sat in the heap until GC.
  • Key-file path: passwordBytes was concatenated into the returned material and then left unzeroed.

Change

  • No-key-file path: return passwordBytes directly. It is already a fresh, exact-length Uint8Array, so the copy was redundant, and returning it means the caller's secureErase(baseMaterial) lands on the one copy that exists.
  • Key-file path: secureErase(passwordBytes) after it is copied into the returned buffer.

This closes the only memory-hygiene gap that survived verification of a broader review. The reported v2/worker "key-file leak", "main-thread leak", and "worker finally" findings were checked against the source and are not real: secureErase zeroes the backing ArrayBuffer, and every v2 path passes a view over the same key-file buffer that the caller's finally erases, so no separate copy lingers.

Why it is safe

Byte-neutral. The KDF input is identical, so derived keys and container bytes do not change. The v1 encrypt and decrypt paths both already erase the returned baseMaterial.

Tests

  • npm run typecheck: clean.
  • npm run test:crypto: 45 passed, 0 failed.
  • npm run test:keymaker: 238 passed, 0 failed.

The change is byte-neutral, so the existing regression and conformance suites are the correctness control; there is no new externally observable behavior to assert.

🤖 Generated with Claude Code


Generated by Claude Code

buildBaseMaterial encoded the NFC password into passwordBytes and, in the
no-key-file path, copied it into a second buffer that the caller erases,
leaving the original passwordBytes copy unzeroed until garbage collection.
Return the encoded bytes directly so the caller's secureErase lands on the
one copy that exists. In the key-file path, zero passwordBytes after it is
concatenated into the returned material.

Byte-neutral: the KDF input is unchanged, so derived keys and container
bytes are identical. Verified by test:crypto (45 passed) and
test:keymaker (238 passed).
@404SecNotFound
404SecNotFound merged commit ae95aa6 into main Sep 4, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant