The wallet-hardening memzero cluster. Uses the file's established sodium_memzero
pattern (matching the existing lambda-capture scrub at app_network.cpp:2885 and the JSON
scrub at :4025) rather than a new type, since importPrivateKey/sweepPrivateKey are
fund-moving code.
- W4-1 importPrivateKey / sweepPrivateKey: the spending/viewing key was copied ≥3×
(calling frame -> worker-lambda capture -> JSON params) and never scrubbed. Now zeroed
on all paths: the calling-frame copy after the worker post, the lambda's captured copy
(lambda made mutable, zeroed once the request is sent), and the request params copy.
- W4-3 exportAllKeys / backupWallet: the concatenated all-keys buffer is now zeroed after
the consumer uses it, and the backup is written via
Platform::writeFileAtomically(..., restrictPermissions=true) — atomic and owner-only
(0600) — instead of a umask-default std::ofstream that left it world-readable.
- W2-3 decrypt-wallet passphrase: std::move-captured into the worker lambda (no plaintext
copy left in the calling frame) and sodium_memzero'd right after unlockWallet, its only
use.
Not unit-testable (no observable RPC effect — the key value sent to the daemon is
unchanged; only post-use memory zeroing is added). Build-clean; ctest 1/1. See
docs/wallet-hardening.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>