simplewallet: quote notes in transfer exports
What changed, and why it matters
This change fixes a CSV export bug in Monero's command-line wallet. User-written notes attached to transfers were written into the export file without surrounding quotes, while other fields were quoted. If a note contained a comma, the exported CSV would have extra columns, and if it contained a quote, the file could become malformed. This is a data-integrity/formatting fix rather than a code-execution vulnerability, but it could mislead users or break import into spreadsheet software.
Treat as a low-severity data-integrity bug. Users who previously exported transfer notes containing commas, quotes, or formula-like characters should re-export after applying the patch and verify CSV imports. Consider also sanitizing note content for CSV formula-injection characters if the export is intended to be opened in spreadsheet applications.
Security signals we found
CSV injection / formula injection is not addressed (no sanitization of leading =, +, -, @, tab, or newline characters)
User-controlled string inserted into a structured export format without proper quoting/escaping before the fix
Fix applies standard CSV double-quote escaping for embedded quotes
No memory safety, cryptographic, or consensus changes
Evidence from the diff
In simple_wallet::export_transfers, the boost::format string previously quoted most fields but left the note field as a bare %s. The patch wraps the note in double quotes and escapes embedded double quotes by doubling them (CSV-style escaping). This prevents commas or quotes inside transfer notes from corrupting the CSV structure. The change is localized to the export formatting logic and does not alter transaction handling, cryptography, or network behavior.
Changed components
src/simplewallet/simplewallet.cppsimple_wallet::export_transfersCSV export of transfer historyInspect captured patch +5 / −2
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 99d7932..6a8f984 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -8673,7 +8673,7 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_)
<< std::endl;
uint64_t running_balance = 0;
- auto formatter = boost::format("%8.8llu,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%106.106s,%20.20s,\"%s\",%s,%s");
+ auto formatter = boost::format("%8.8llu,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%106.106s,%20.20s,\"%s\",\"%s\",%s");
for (const auto& transfer : all_transfers)
{
@@ -8695,6 +8695,9 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_)
key_string = get_tx_key_stream(tx_key, additional_tx_keys);
}
+ std::string note = transfer.note;
+ boost::replace_all(note, "\"", "\"\"");
+
file << formatter
% transfer.block
% transfer.direction
@@ -8708,7 +8711,7 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_)
% (transfer.outputs.size() ? transfer.outputs[0].first : "-")
% (transfer.outputs.size() ? print_money(transfer.outputs[0].second) : "")
% boost::algorithm::join(transfer.index | boost::adaptors::transformed([](uint32_t i) { return std::to_string(i); }), ", ")
- % transfer.note
+ % note
% key_string
<< std::endl;
Why this scored 33/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.