fix(security): harden untrusted-input parsing (Tier 4 audit items)

- export: neutralize CSV/spreadsheet formula injection in transaction export —
  escapeCSV() now prefixes fields beginning with = + - @ / tab / CR with a
  single quote so a hostile memo/address cannot execute on open (F13-1).
- console: preserve explicitly-quoted empty arguments in ParseConsoleCommandArgs
  so a "" no longer collapses and shifts later positional RPC params; adds a
  regression assertion to testConsoleInputModel (F14-1).
- send: copy pending payment-URI address/memo with snprintf("%s") instead of
  strncpy(…, sizeof-1), which does not NUL-terminate on truncation (F8-2).

All build clean (full-node + tests) and the suite passes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-22 01:56:13 -05:00
co-authored by Claude Fable 5
parent 5554016029
commit 13788b5dd0
4 changed files with 27 additions and 9 deletions
+6
View File
@@ -2378,6 +2378,12 @@ void testConsoleInputModel()
auto args = dragonx::ui::ParseConsoleCommandArgs("z_sendmany \"from addr\" [{\"address\":\"zs\",\"amount\":1.25}] true");
EXPECT_EQ(args.size(), static_cast<size_t>(4));
EXPECT_EQ(args[1], std::string("from addr"));
// An explicitly-quoted empty argument must be preserved (not dropped), otherwise
// later positional RPC params silently shift by one (F14-1).
auto emptyArgs = dragonx::ui::ParseConsoleCommandArgs("walletpassphrase \"\" 60");
EXPECT_EQ(emptyArgs.size(), static_cast<size_t>(3));
EXPECT_EQ(emptyArgs[1], std::string(""));
EXPECT_EQ(emptyArgs[2], std::string("60"));
auto call = dragonx::ui::BuildConsoleRpcCall("setgenerate true 4");
EXPECT_TRUE(call.valid);
EXPECT_EQ(call.method, std::string("setgenerate"));