security(hygiene): best-effort scrubbing of residual in-memory secret copies (Tier 4)
Defense-in-depth against a local attacker / core dump reading un-zeroed heap copies of secrets (threat model is local, not remote). Best-effort by nature — std::string SSO/reallocation and ImGui buffer growth can still strand copies — so these shrink the exposure window rather than guarantee absence: - rpc_client performCall: a scope guard now sodium_memzeroes the request body + payload tree (walletpassphrase / *_importkey args) after the call and detaches CURLOPT_POSTFIELDS. Request content sent to curl is unchanged. - New ui::scrubImGuiInputTextState() zeroes ImGui's retained InputText buffers (live/revert/callback/deactivated) — the app memzeroed its own char[]s but ImGui kept copies. Called from wipeSecrets()/wipeDisplayedSecrets(). PINNED to ImGui 1.92.6 via a #error guard so a vendored bump forces a re-audit (the stb undo buffer is an incomplete type in the header, so it's left as a noted gap). - Lite exportSeed/exportPrivateKeys wipe result.value + the parsed JSON tree. - Seed-word grid (SplitSeedWords/RenderSeedWordGrid) zeroes its per-frame word and cell copies; the wizard word/chip vectors are zeroed before clearing. - ChatStore::clear() + ResetChatTab() zero decrypted message bodies on lock/switch/teardown. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include "chat_store.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sodium.h>
|
||||
|
||||
namespace dragonx::chat {
|
||||
|
||||
@@ -112,6 +113,10 @@ std::vector<ChatMessage> ChatStore::eraseConversation(const std::string& convers
|
||||
}
|
||||
|
||||
void ChatStore::clear() {
|
||||
// Zero decrypted plaintext (message bodies + peer address) before dropping them — clear() runs on
|
||||
// wallet lock / switch / teardown, and the freed std::strings would otherwise linger in the heap.
|
||||
auto wipe = [](std::string& s) { if (!s.empty()) sodium_memzero(&s[0], s.size()); s.clear(); };
|
||||
for (auto& m : messages_) { wipe(m.body); wipe(m.fail_reason); wipe(m.peer_zaddr); }
|
||||
messages_.clear();
|
||||
seen_.clear();
|
||||
txid_index_.clear(); // drop the History-badge txid copies too (revision_ below invalidates the memo)
|
||||
|
||||
Reference in New Issue
Block a user