From 3d3a391ef43b1ac09160f4d572d5fbf85f249dc8 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 18 Jun 2026 13:34:27 +0200 Subject: qml: escape untrusted text in remaining RichText views Extends the escaping from commit 23ec5eb6 to the RichText sinks it did not cover: the transaction note in the tx details popup (History), the wallet name and account label in the send confirmation (TxConfirmationDialog), the address label on the merchant page (Merchant), and the wallet path on the info page (SettingsInfo). These were interpolated unescaped, so a value containing markup is rendered as rich text. The transaction note is the notable case: it can be set from a payment request's tx_description, so it is attacker influenced. Escape these fields with Utils.htmlEscape. Set the send confirmation From field to Text.RichText explicitly so the escaped entities decode in both of its branches; the single-account branch contains no tag and would otherwise render as plain text and show the raw entity. --- components/TxConfirmationDialog.qml | 5 +++-- pages/History.qml | 2 +- pages/merchant/Merchant.qml | 2 +- pages/settings/SettingsInfo.qml | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/components/TxConfirmationDialog.qml b/components/TxConfirmationDialog.qml index 1700aa0a..51da022f 100644 --- a/components/TxConfirmationDialog.qml +++ b/components/TxConfirmationDialog.qml @@ -242,6 +242,7 @@ Rectangle { Layout.fillWidth: true font.pixelSize: 15 color: MoneroComponents.Style.defaultFontColor + textFormat: Text.RichText text: { if (currentWallet) { var walletTitle = function() { @@ -257,9 +258,9 @@ Rectangle { if (appWindow.currentWallet.numSubaddressAccounts() > 1) { var currentSubaddressAccount = currentWallet.currentSubaddressAccount; var currentAccountLabel = currentWallet.getSubaddressLabel(currentWallet.currentSubaddressAccount, 0); - return walletTitle() + " (" + walletName + ")" + "
" + qsTr("Account #") + currentSubaddressAccount + (currentAccountLabel !== "" ? " (" + currentAccountLabel + ")" : "") + translationManager.emptyString; + return walletTitle() + " (" + Utils.htmlEscape(walletName) + ")" + "
" + qsTr("Account #") + currentSubaddressAccount + (currentAccountLabel !== "" ? " (" + Utils.htmlEscape(currentAccountLabel) + ")" : "") + translationManager.emptyString; } else { - return walletTitle() + " (" + walletName + ")" + translationManager.emptyString; + return walletTitle() + " (" + Utils.htmlEscape(walletName) + ")" + translationManager.emptyString; } } else { return ""; diff --git a/pages/History.qml b/pages/History.qml index d9132e3b..6871405d 100644 --- a/pages/History.qml +++ b/pages/History.qml @@ -1746,7 +1746,7 @@ Rectangle { + (paymentId ? trStart + qsTr("Payment ID:") + trMiddle + paymentId + trEnd : "") + (integratedAddress ? trStart + qsTr("Integrated address") + ":" + trMiddle + integratedAddress + trEnd : "") + (tx_key ? trStart + qsTr("Tx key:") + trMiddle + tx_key + trEnd : "") - + (tx_note ? trStart + qsTr("Tx note:") + trMiddle + tx_note + trEnd : "") + + (tx_note ? trStart + qsTr("Tx note:") + trMiddle + Utils.htmlEscape(tx_note) + trEnd : "") + (destinations ? trStart + qsTr("Destinations:") + trMiddle + destinations + trEnd : "") + (rings ? trStart + qsTr("Rings:") + trMiddle + rings + trEnd : "") + "" diff --git a/pages/merchant/Merchant.qml b/pages/merchant/Merchant.qml index 560484b1..86d47560 100644 --- a/pages/merchant/Merchant.qml +++ b/pages/merchant/Merchant.qml @@ -295,7 +295,7 @@ Item { color: "white" text: "%1: %2 (%3)" .arg(qsTr("Currently selected address")) - .arg(addressLabel) + .arg(Utils.htmlEscape(addressLabel)) .arg(qsTr("Change")) + translationManager.emptyString textFormat: Text.RichText themeTransition: false diff --git a/pages/settings/SettingsInfo.qml b/pages/settings/SettingsInfo.qml index ad152d63..e126383a 100644 --- a/pages/settings/SettingsInfo.qml +++ b/pages/settings/SettingsInfo.qml @@ -142,7 +142,7 @@ Rectangle { \ - %1".arg(walletPath) + %1".arg(Utils.htmlEscape(walletPath)) textFormat: Text.RichText onLinkActivated: oshelper.openContainingFolder(walletPath) -- cgit v1.2.3