fix: security-audit remediation (15 findings), empty-wallet warning, and send/chat/console/shutdown UX

Security audit remediation (15 confirmed findings from the codebase audit):
- H-02: scrub+delete the decrypt-flow plaintext key export on ALL exit paths
  (RAII guard) and purge stale obsidiandecryptexport* files at startup.
- M-01/L-03/L-04/L-05/L-07: sodium_memzero the Set-PIN and encrypt-PIN worker
  passphrase/PIN copies, the RPC Basic-auth string (auth_), the exported/imported
  key buffers (App::wipeSecrets, called from ~App and before main's _Exit), and
  the first-run wizard "Skip" buffers.
- M-03/M-04/M-05/L-06: return locked COPIES from XmrigManager/EmbeddedDaemon
  getters (dedicated error_mutex_; DaemonController::lastError now by value),
  route xmrig last_error_ writes through a locked setter, and wrap
  shutdown_status_/wizard_stop_status_ in a locking GuardedStatus
  (wizard_stopping_external_ -> std::atomic).
- M-02: persist after a console send/shield/import in the lite backend.
- L-01: require the confirm click for z_shieldcoinbase/z_mergetoaddress.
- L-02: quote/escape each Windows daemon argv per the MSDN CommandLineToArgvW rules.
- L-08: pin json/tomlplusplus/libwebp FetchContent to immutable commit SHAs.
- I-01: extract updater archives from the already-verified in-memory buffer
  (no disk re-read TOCTOU).

Feature: warn once (full-node) when the active wallet loads empty while a sibling
wallet file in the datadir holds keys. A funded salvage wallet.<ts>.bak routes to
the recovery/Restore flow; a funded sibling .dat routes to the wallet manager.
Per-wallet-file dismissal; gated on synced + address-list-loaded to avoid false
positives on warm reconnect / spent-down wallets.

UX fixes:
- send: show the TOTAL balance (with a spendable "available" note) in the source
  dropdown and keep pending-change addresses visible.
- chat: insert emoji at the cursor position; restrict new-chat recipients to
  shielded (z) addresses.
- console: optional auto-focus of the command input on tab open (off by default).
- shutdown: when "stop external daemon" is on, keep the shutdown screen up until
  the external node actually exits, showing live status.

Adversarially reviewed; verified across full-node, lite, and Windows builds; tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-18 13:18:49 -05:00
parent ea26c0cbbb
commit 6ee81a5abe
40 changed files with 745 additions and 90 deletions

View File

@@ -485,6 +485,17 @@
"download_bootstrap": "Скачать бутстрап",
"dragonx_green": "DragonX (Зелёная)",
"edit": "Редактировать",
"empty_wallet_keys_suffix": "ключей",
"empty_wallet_open_manager": "Открыть менеджер кошельков",
"empty_wallet_restore": "Восстановить мой кошелёк",
"empty_wallet_salvage_body": "Этот кошелёк пуст, потому что предыдущее автоматическое восстановление отложило ваш исходный кошелёк в качестве резервной копии. Ваши монеты почти наверняка находятся в этой копии и не потеряны. Восстановите её, чтобы снова загрузить средства — ничего не удаляется; текущий файл сначала откладывается в сторону.",
"empty_wallet_salvage_headline": "Ваши монеты в безопасности в файле резервной копии.",
"empty_wallet_salvage_title": "Возможно, ваш кошелёк был восстановлен",
"empty_wallet_warning_body": "В этом кошельке нет адресов и средств, но другой файл кошелька в вашей папке DragonX содержит ключи. Ваши монеты, скорее всего, находятся в нём и не потеряны. Откройте менеджер кошельков, чтобы переключиться на кошелёк с вашими средствами.",
"empty_wallet_warning_dismiss": "Больше не предупреждать для этого кошелька",
"empty_wallet_warning_dismiss_tip": "Останавливает это предупреждение только для текущего файла кошелька. Если позже вы переключитесь на другой пустой кошелёк, предупреждение может появиться снова.",
"empty_wallet_warning_headline": "Возможно, вы открыли не тот кошелёк.",
"empty_wallet_warning_title": "Этот кошелёк пуст",
"enc_confirm": "Подтвердите:",
"enc_desc": "Шифрование кошелька защищает ваши приватные ключи паролем. После шифрования демон перезапустится.",
"enc_encrypting": "Шифрование кошелька...",