gui: Avoid pathological QT text/markdown behavior...
What changed, and why it matters
This change alters the Bitcoin Core debug console's text box so that when a user copies selected text, only plain text is placed on the clipboard. Previously, Qt's default behavior could convert the selection into HTML and Markdown formats, which the commit message describes as 'pathological.' The concern is that an attacker who can control text shown in the debug console (for example, error messages or RPC output) might be able to inject malicious content that, if copied and pasted elsewhere, could execute commands or leak data through rich-text features. The patch removes that rich-text conversion entirely.
Treat this as a defense-in-depth hardening change. Users running affected versions should avoid copying untrusted console output into rich-text applications before updating. No immediate emergency action is required, but the fix should be included in the next maintenance release.
Security signals we found
Clipboard mime-type restriction to plaintext only
Override of Qt's default rich-text copy behavior
Reference to 'pathological QT text/markdown behavior' in commit title
Defense against potential HTML/Markdown injection via copied console output
Evidence from the diff
The patch introduces a custom QTextEdit subclass, PlainCopyTextEdit, in src/qt/rpcconsole.h. It overrides createMimeDataFromSelection() to return a QMimeData object containing only text/plain, stripping any HTML or Markdown representation. The debugwindow.ui form is updated to use this subclass for the messagesWidget. This mitigates risks associated with Qt’s internal HTML-to-Markdown conversion when users copy content from the RPC console, which could otherwise carry hidden markup or links.
Changed components
src/qt/forms/debugwindow.uisrc/qt/rpcconsole.hBitcoin Core Qt GUI debug/RPC consoleInspect captured patch +24 / −1
diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui
index eccea143..d1c627bb 100644
--- a/src/qt/forms/debugwindow.ui
+++ b/src/qt/forms/debugwindow.ui
@@ -573,7 +573,7 @@
</layout>
</item>
<item>
- <widget class="QTextEdit" name="messagesWidget">
+ <widget class="PlainCopyTextEdit" name="messagesWidget">
<property name="minimumSize">
<size>
<width>0</width>
@@ -1868,6 +1868,10 @@
<slot>clear()</slot>
</slots>
</customwidget>
+ <customwidget>
+ <class>PlainCopyTextEdit</class>
+ <extends>QTextEdit</extends>
+ </customwidget>
</customwidgets>
<resources>
<include location="../bitcoin.qrc"/>
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index a1b9522b..fe2955cc 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -15,6 +15,9 @@
#include <QByteArray>
#include <QCompleter>
+#include <QMimeData>
+#include <QTextDocumentFragment>
+#include <QTextEdit>
#include <QThread>
#include <QWidget>
@@ -191,4 +194,20 @@ private Q_SLOTS:
void updateAlerts(const QString& warnings);
};
+/**
+ * A version of QTextEdit that only populates plaintext mime data from a
+ * selection, this avoids some bad behavior in QT's HTML->Markdown conversion.
+ */
+class PlainCopyTextEdit : public QTextEdit {
+ Q_OBJECT
+public:
+ using QTextEdit::QTextEdit;
+protected:
+ QMimeData* createMimeDataFromSelection() const override {
+ auto md = new QMimeData();
+ md->setText(textCursor().selection().toPlainText());
+ return md;
+ }
+};
+
#endif // BITCOIN_QT_RPCCONSOLE_H
Why this scored 35/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.