Your message dated Thu, 10 Jul 2025 12:24:25 +0000
with message-id <e1uzqk9-00egdv...@respighi.debian.org>
and subject line unblock qbittorrent
has caused the Debian Bug report #1108869,
regarding unblock: qbittorrent/5.1.0-2
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact ow...@bugs.debian.org
immediately.)


-- 
1108869: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1108869
Debian Bug Tracking System
Contact ow...@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
X-Debbugs-Cc: qbittorr...@packages.debian.org
Control: affects -1 + src:qbittorrent
User: release.debian....@packages.debian.org
Usertags: unblock

Please unblock package qbittorrent

Package not yet uploaded.

To fix bug #1108843 with security issue (no DSA yet)

I've two choices: backport 2 patches from 5.1.2 or release the 5.1.2
version over 5.1.0

debdiff at the bottom.

What is your opinion?

Christian

$ cat qbittorrent_5.1.0-2.debdiff
diff -Nru qbittorrent-5.1.0/debian/changelog qbittorrent-5.1.0/debian/changelog
--- qbittorrent-5.1.0/debian/changelog  2025-04-28 09:24:06.000000000 +0200
+++ qbittorrent-5.1.0/debian/changelog  2025-07-06 16:40:13.000000000 +0200
@@ -1,3 +1,10 @@
+qbittorrent (5.1.0-2) unstable; urgency=medium
+
+  * Add two patches from 5.1.2 version to fix security issues: WebAPI, Rss
+    and Search modules (Closes: #1108843)
+
+ -- Christian Marillat <maril...@debian.org>  Sun, 06 Jul 2025 16:40:13 +0200
+
 qbittorrent (5.1.0-1) unstable; urgency=medium
 
   * New upstream release.
diff -Nru 
qbittorrent-5.1.0/debian/patches/4f94eac235cefa8b83489cb3135dad87fcbed1e3.patch 
qbittorrent-5.1.0/debian/patches/4f94eac235cefa8b83489cb3135dad87fcbed1e3.patch
--- 
qbittorrent-5.1.0/debian/patches/4f94eac235cefa8b83489cb3135dad87fcbed1e3.patch 
    1970-01-01 01:00:00.000000000 +0100
+++ 
qbittorrent-5.1.0/debian/patches/4f94eac235cefa8b83489cb3135dad87fcbed1e3.patch 
    2025-07-06 16:39:40.000000000 +0200
@@ -0,0 +1,191 @@
+From d379fa30350bd2aaf50656c7cd5fbaf6f6219773 Mon Sep 17 00:00:00 2001
+From: "Vladimir Golovnev (Glassez)" <glas...@yandex.ru>
+Date: Mon, 23 Jun 2025 13:14:37 +0300
+Subject: [PATCH 1/2] Prevent opening local files if web page is expected
+
+---
+ src/base/rss/rss_article.cpp       | 20 ++++++++++----------
+ src/gui/rss/rsswidget.cpp          |  4 ++--
+ src/gui/search/searchjobwidget.cpp |  8 ++++----
+ 3 files changed, 16 insertions(+), 16 deletions(-)
+
+--- a/src/base/rss/rss_article.cpp
++++ b/src/base/rss/rss_article.cpp
+@@ -48,16 +48,16 @@ const QString Article::KeyIsRead = u"isR
+ 
+ Article::Article(Feed *feed, const QVariantHash &varHash)
+     : QObject(feed)
+-    , m_feed(feed)
+-    , m_guid(varHash.value(KeyId).toString())
+-    , m_date(varHash.value(KeyDate).toDateTime())
+-    , m_title(varHash.value(KeyTitle).toString())
+-    , m_author(varHash.value(KeyAuthor).toString())
+-    , m_description(varHash.value(KeyDescription).toString())
+-    , m_torrentURL(varHash.value(KeyTorrentURL).toString())
+-    , m_link(varHash.value(KeyLink).toString())
+-    , m_isRead(varHash.value(KeyIsRead, false).toBool())
+-    , m_data(varHash)
++    , m_feed {feed}
++    , m_guid {varHash.value(KeyId).toString()}
++    , m_date {varHash.value(KeyDate).toDateTime()}
++    , m_title {varHash.value(KeyTitle).toString()}
++    , m_author {varHash.value(KeyAuthor).toString()}
++    , m_description {varHash.value(KeyDescription).toString()}
++    , m_torrentURL {varHash.value(KeyTorrentURL).toString()}
++    , m_link {varHash.value(KeyLink).toString()}
++    , m_isRead {varHash.value(KeyIsRead, false).toBool()}
++    , m_data {varHash}
+ {
+ }
+ 
+--- a/src/gui/rss/rsswidget.cpp
++++ b/src/gui/rss/rsswidget.cpp
+@@ -40,6 +40,7 @@
+ #include <QString>
+ 
+ #include "base/global.h"
++#include "base/logger.h"
+ #include "base/net/downloadmanager.h"
+ #include "base/preferences.h"
+ #include "base/rss/rss_article.h"
+@@ -415,16 +416,52 @@ void RSSWidget::downloadSelectedTorrents
+ // open the url of the selected RSS articles in the Web browser
+ void RSSWidget::openSelectedArticlesUrls()
+ {
++    qsizetype emptyLinkCount = 0;
++    qsizetype badLinkCount = 0;
++    QString articleTitle;
+     for (QListWidgetItem *item : 
asConst(m_ui->articleListWidget->selectedItems()))
+     {
+         auto *article = item->data(Qt::UserRole).value<RSS::Article *>();
+         Q_ASSERT(article);
+ 
+-        // Mark as read
+         article->markAsRead();
+ 
+-        if (!article->link().isEmpty())
+-            QDesktopServices::openUrl(QUrl(article->link()));
++        const QString articleLink = article->link();
++        const QUrl articleLinkURL {articleLink};
++        if (articleLinkURL.isEmpty()) [[unlikely]]
++        {
++            if (articleTitle.isEmpty())
++                articleTitle = article->title();
++            ++emptyLinkCount;
++        }
++        else if (articleLinkURL.isLocalFile()) [[unlikely]]
++        {
++            if (badLinkCount == 0)
++                articleTitle = article->title();
++            ++badLinkCount;
++
++            LogMsg(tr("Blocked opening RSS article URL. URL pointing to local 
file might be malicious behaviour. Article: \"%1\". URL: \"%2\".")
++                    .arg(article->title(), articleLink), Log::WARNING);
++        }
++        else [[likely]]
++        {
++            QDesktopServices::openUrl(articleLinkURL);
++        }
++    }
++
++    if (badLinkCount > 0)
++    {
++        QString message = tr("Blocked opening RSS article URL. The following 
article URL is pointing to local file and it may be malicious 
behaviour:\n%1").arg(articleTitle);
++        if (badLinkCount > 1)
++            message.append(u"\n" + tr("There are %1 more articles with the 
same issue.").arg(badLinkCount - 1));
++        QMessageBox::warning(this, u"qBittorrent"_s, message, 
QMessageBox::Ok);
++    }
++    else if (emptyLinkCount > 0)
++    {
++        QString message = tr("The following article has no news URL 
provided:\n%1").arg(articleTitle);
++        if (emptyLinkCount > 1)
++            message.append(u"\n" + tr("There are %1 more articles with the 
same issue.").arg(emptyLinkCount - 1));
++        QMessageBox::warning(this, u"qBittorrent"_s, message, 
QMessageBox::Ok);
+     }
+ }
+ 
+--- a/src/gui/search/searchjobwidget.cpp
++++ b/src/gui/search/searchjobwidget.cpp
+@@ -35,10 +35,12 @@
+ #include <QHeaderView>
+ #include <QKeyEvent>
+ #include <QMenu>
++#include <QMessageBox>
+ #include <QPalette>
+ #include <QStandardItemModel>
+ #include <QUrl>
+ 
++#include "base/logger.h"
+ #include "base/preferences.h"
+ #include "base/search/searchdownloadhandler.h"
+ #include "base/search/searchhandler.h"
+@@ -319,15 +321,52 @@ void SearchJobWidget::downloadTorrents(c
+         downloadTorrent(rowIndex, option);
+ }
+ 
+-void SearchJobWidget::openTorrentPages() const
++void SearchJobWidget::openTorrentPages()
+ {
+-    const QModelIndexList rows 
{m_ui->resultsBrowser->selectionModel()->selectedRows()};
++    const QModelIndexList rows = 
m_ui->resultsBrowser->selectionModel()->selectedRows();
++    qsizetype emptyLinkCount = 0;
++    qsizetype badLinkCount = 0;
++    QString warningEntryName;
+     for (const QModelIndex &rowIndex : rows)
+     {
+-        const QString descrLink = m_proxyModel->data(
+-                    m_proxyModel->index(rowIndex.row(), 
SearchSortModel::DESC_LINK)).toString();
+-        if (!descrLink.isEmpty())
+-            QDesktopServices::openUrl(QUrl::fromEncoded(descrLink.toUtf8()));
++        const QString entryName = m_proxyModel->index(rowIndex.row(), 
SearchSortModel::NAME).data().toString();
++        const QString descrLink = m_proxyModel->index(rowIndex.row(), 
SearchSortModel::DESC_LINK).data().toString();
++
++        const QUrl descrLinkURL {descrLink};
++        if (descrLinkURL.isEmpty()) [[unlikely]]
++        {
++            if (warningEntryName.isEmpty())
++                warningEntryName = entryName;
++            ++emptyLinkCount;
++        }
++        else if (descrLinkURL.isLocalFile()) [[unlikely]]
++        {
++            if (badLinkCount == 0)
++                warningEntryName = entryName;
++            ++badLinkCount;
++
++            LogMsg(tr("Blocked opening search result description page URL. 
URL pointing to local file might be malicious behaviour. Name: \"%1\". URL: 
\"%2\".")
++                    .arg(entryName, descrLink), Log::WARNING);
++        }
++        else [[likely]]
++        {
++            QDesktopServices::openUrl(descrLinkURL);
++        }
++    }
++
++    if (badLinkCount > 0)
++    {
++        QString message = tr("Blocked opening search result description page 
URL. The following result URL is pointing to local file and it may be malicious 
behaviour:\n%1").arg(warningEntryName);
++        if (badLinkCount > 1)
++            message.append(u"\n" + tr("There are %1 more results with the 
same issue.").arg(badLinkCount - 1));
++        QMessageBox::warning(this, u"qBittorrent"_s, message, 
QMessageBox::Ok);
++    }
++    else if (emptyLinkCount > 0)
++    {
++        QString message = tr("Entry \"%1\" has no description page URL 
provided.").arg(warningEntryName);
++        if (emptyLinkCount > 1)
++            message.append(u"\n" + tr("There are %1 more entries with the 
same issue.").arg(emptyLinkCount - 1));
++        QMessageBox::warning(this, u"qBittorrent"_s, message, 
QMessageBox::Ok);
+     }
+ }
+ 
+--- a/src/gui/search/searchjobwidget.h
++++ b/src/gui/search/searchjobwidget.h
+@@ -127,7 +127,7 @@ private:
+     void onUIThemeChanged();
+ 
+     void downloadTorrents(AddTorrentOption option = 
AddTorrentOption::Default);
+-    void openTorrentPages() const;
++    void openTorrentPages();
+     void copyTorrentURLs() const;
+     void copyTorrentDownloadLinks() const;
+     void copyTorrentNames() const;
diff -Nru 
qbittorrent-5.1.0/debian/patches/9b29d37d210f28f46eb4758611d7b06f4603b9d1.patch 
qbittorrent-5.1.0/debian/patches/9b29d37d210f28f46eb4758611d7b06f4603b9d1.patch
--- 
qbittorrent-5.1.0/debian/patches/9b29d37d210f28f46eb4758611d7b06f4603b9d1.patch 
    1970-01-01 01:00:00.000000000 +0100
+++ 
qbittorrent-5.1.0/debian/patches/9b29d37d210f28f46eb4758611d7b06f4603b9d1.patch 
    2025-07-06 16:39:44.000000000 +0200
@@ -0,0 +1,37 @@
+From 9b29d37d210f28f46eb4758611d7b06f4603b9d1 Mon Sep 17 00:00:00 2001
+From: Chocobo1 <choco...@users.noreply.github.com>
+Date: Mon, 30 Jun 2025 01:39:03 +0800
+Subject: [PATCH] WebAPI: Trim leading whitespaces on Run External Program
+ fields
+
+Hacked qbt instances may contain malicious script placed in Run External 
Program and the script
+will attempt to hide itself by adding a lot whitespaces at the start of the 
command string.
+Users may mistake the field of being empty but is actually not.
+So trim the leading whitespaces to easily expose the malicious script.
+
+Note that GUI already trim the fields and only WebAPI doesn't trim them. This 
patch will unify
+the behavior.
+Related: 
https://github.com/qbittorrent/docker-qbittorrent-nox/issues/71#issuecomment-2993567440
+
+PR #22939.
+---
+ src/webui/api/appcontroller.cpp | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/src/webui/api/appcontroller.cpp
++++ b/src/webui/api/appcontroller.cpp
+@@ -673,12 +673,12 @@ void AppController::setPreferencesAction
+     if (hasKey(u"autorun_on_torrent_added_enabled"_s))
+         pref->setAutoRunOnTorrentAddedEnabled(it.value().toBool());
+     if (hasKey(u"autorun_on_torrent_added_program"_s))
+-        pref->setAutoRunOnTorrentAddedProgram(it.value().toString());
++        
pref->setAutoRunOnTorrentAddedProgram(it.value().toString().trimmed());
+     // Run an external program on torrent finished
+     if (hasKey(u"autorun_enabled"_s))
+         pref->setAutoRunOnTorrentFinishedEnabled(it.value().toBool());
+     if (hasKey(u"autorun_program"_s))
+-        pref->setAutoRunOnTorrentFinishedProgram(it.value().toString());
++        
pref->setAutoRunOnTorrentFinishedProgram(it.value().toString().trimmed());
+ 
+     // Connection
+     // Listening Port
diff -Nru qbittorrent-5.1.0/debian/patches/series 
qbittorrent-5.1.0/debian/patches/series
--- qbittorrent-5.1.0/debian/patches/series     1970-01-01 01:00:00.000000000 
+0100
+++ qbittorrent-5.1.0/debian/patches/series     2025-07-06 16:39:32.000000000 
+0200
@@ -0,0 +1,2 @@
+4f94eac235cefa8b83489cb3135dad87fcbed1e3.patch
+9b29d37d210f28f46eb4758611d7b06f4603b9d1.patch
diff -Nru qbittorrent-5.1.0/debian/changelog qbittorrent-5.1.0/debian/changelog
--- qbittorrent-5.1.0/debian/changelog  2025-04-28 09:24:06.000000000 +0200
+++ qbittorrent-5.1.0/debian/changelog  2025-07-06 16:40:13.000000000 +0200
@@ -1,3 +1,10 @@
+qbittorrent (5.1.0-2) unstable; urgency=medium
+
+  * Add two patches from 5.1.2 version to fix security issues: WebAPI, Rss
+    and Search modules (Closes: #1108843)
+
+ -- Christian Marillat <maril...@debian.org>  Sun, 06 Jul 2025 16:40:13 +0200
+
 qbittorrent (5.1.0-1) unstable; urgency=medium
 
   * New upstream release.
diff -Nru 
qbittorrent-5.1.0/debian/patches/4f94eac235cefa8b83489cb3135dad87fcbed1e3.patch 
qbittorrent-5.1.0/debian/patches/4f94eac235cefa8b83489cb3135dad87fcbed1e3.patch
--- 
qbittorrent-5.1.0/debian/patches/4f94eac235cefa8b83489cb3135dad87fcbed1e3.patch 
    1970-01-01 01:00:00.000000000 +0100
+++ 
qbittorrent-5.1.0/debian/patches/4f94eac235cefa8b83489cb3135dad87fcbed1e3.patch 
    2025-07-06 16:39:40.000000000 +0200
@@ -0,0 +1,191 @@
+From d379fa30350bd2aaf50656c7cd5fbaf6f6219773 Mon Sep 17 00:00:00 2001
+From: "Vladimir Golovnev (Glassez)" <glas...@yandex.ru>
+Date: Mon, 23 Jun 2025 13:14:37 +0300
+Subject: [PATCH 1/2] Prevent opening local files if web page is expected
+
+---
+ src/base/rss/rss_article.cpp       | 20 ++++++++++----------
+ src/gui/rss/rsswidget.cpp          |  4 ++--
+ src/gui/search/searchjobwidget.cpp |  8 ++++----
+ 3 files changed, 16 insertions(+), 16 deletions(-)
+
+--- a/src/base/rss/rss_article.cpp
++++ b/src/base/rss/rss_article.cpp
+@@ -48,16 +48,16 @@ const QString Article::KeyIsRead = u"isR
+ 
+ Article::Article(Feed *feed, const QVariantHash &varHash)
+     : QObject(feed)
+-    , m_feed(feed)
+-    , m_guid(varHash.value(KeyId).toString())
+-    , m_date(varHash.value(KeyDate).toDateTime())
+-    , m_title(varHash.value(KeyTitle).toString())
+-    , m_author(varHash.value(KeyAuthor).toString())
+-    , m_description(varHash.value(KeyDescription).toString())
+-    , m_torrentURL(varHash.value(KeyTorrentURL).toString())
+-    , m_link(varHash.value(KeyLink).toString())
+-    , m_isRead(varHash.value(KeyIsRead, false).toBool())
+-    , m_data(varHash)
++    , m_feed {feed}
++    , m_guid {varHash.value(KeyId).toString()}
++    , m_date {varHash.value(KeyDate).toDateTime()}
++    , m_title {varHash.value(KeyTitle).toString()}
++    , m_author {varHash.value(KeyAuthor).toString()}
++    , m_description {varHash.value(KeyDescription).toString()}
++    , m_torrentURL {varHash.value(KeyTorrentURL).toString()}
++    , m_link {varHash.value(KeyLink).toString()}
++    , m_isRead {varHash.value(KeyIsRead, false).toBool()}
++    , m_data {varHash}
+ {
+ }
+ 
+--- a/src/gui/rss/rsswidget.cpp
++++ b/src/gui/rss/rsswidget.cpp
+@@ -40,6 +40,7 @@
+ #include <QString>
+ 
+ #include "base/global.h"
++#include "base/logger.h"
+ #include "base/net/downloadmanager.h"
+ #include "base/preferences.h"
+ #include "base/rss/rss_article.h"
+@@ -415,16 +416,52 @@ void RSSWidget::downloadSelectedTorrents
+ // open the url of the selected RSS articles in the Web browser
+ void RSSWidget::openSelectedArticlesUrls()
+ {
++    qsizetype emptyLinkCount = 0;
++    qsizetype badLinkCount = 0;
++    QString articleTitle;
+     for (QListWidgetItem *item : 
asConst(m_ui->articleListWidget->selectedItems()))
+     {
+         auto *article = item->data(Qt::UserRole).value<RSS::Article *>();
+         Q_ASSERT(article);
+ 
+-        // Mark as read
+         article->markAsRead();
+ 
+-        if (!article->link().isEmpty())
+-            QDesktopServices::openUrl(QUrl(article->link()));
++        const QString articleLink = article->link();
++        const QUrl articleLinkURL {articleLink};
++        if (articleLinkURL.isEmpty()) [[unlikely]]
++        {
++            if (articleTitle.isEmpty())
++                articleTitle = article->title();
++            ++emptyLinkCount;
++        }
++        else if (articleLinkURL.isLocalFile()) [[unlikely]]
++        {
++            if (badLinkCount == 0)
++                articleTitle = article->title();
++            ++badLinkCount;
++
++            LogMsg(tr("Blocked opening RSS article URL. URL pointing to local 
file might be malicious behaviour. Article: \"%1\". URL: \"%2\".")
++                    .arg(article->title(), articleLink), Log::WARNING);
++        }
++        else [[likely]]
++        {
++            QDesktopServices::openUrl(articleLinkURL);
++        }
++    }
++
++    if (badLinkCount > 0)
++    {
++        QString message = tr("Blocked opening RSS article URL. The following 
article URL is pointing to local file and it may be malicious 
behaviour:\n%1").arg(articleTitle);
++        if (badLinkCount > 1)
++            message.append(u"\n" + tr("There are %1 more articles with the 
same issue.").arg(badLinkCount - 1));
++        QMessageBox::warning(this, u"qBittorrent"_s, message, 
QMessageBox::Ok);
++    }
++    else if (emptyLinkCount > 0)
++    {
++        QString message = tr("The following article has no news URL 
provided:\n%1").arg(articleTitle);
++        if (emptyLinkCount > 1)
++            message.append(u"\n" + tr("There are %1 more articles with the 
same issue.").arg(emptyLinkCount - 1));
++        QMessageBox::warning(this, u"qBittorrent"_s, message, 
QMessageBox::Ok);
+     }
+ }
+ 
+--- a/src/gui/search/searchjobwidget.cpp
++++ b/src/gui/search/searchjobwidget.cpp
+@@ -35,10 +35,12 @@
+ #include <QHeaderView>
+ #include <QKeyEvent>
+ #include <QMenu>
++#include <QMessageBox>
+ #include <QPalette>
+ #include <QStandardItemModel>
+ #include <QUrl>
+ 
++#include "base/logger.h"
+ #include "base/preferences.h"
+ #include "base/search/searchdownloadhandler.h"
+ #include "base/search/searchhandler.h"
+@@ -319,15 +321,52 @@ void SearchJobWidget::downloadTorrents(c
+         downloadTorrent(rowIndex, option);
+ }
+ 
+-void SearchJobWidget::openTorrentPages() const
++void SearchJobWidget::openTorrentPages()
+ {
+-    const QModelIndexList rows 
{m_ui->resultsBrowser->selectionModel()->selectedRows()};
++    const QModelIndexList rows = 
m_ui->resultsBrowser->selectionModel()->selectedRows();
++    qsizetype emptyLinkCount = 0;
++    qsizetype badLinkCount = 0;
++    QString warningEntryName;
+     for (const QModelIndex &rowIndex : rows)
+     {
+-        const QString descrLink = m_proxyModel->data(
+-                    m_proxyModel->index(rowIndex.row(), 
SearchSortModel::DESC_LINK)).toString();
+-        if (!descrLink.isEmpty())
+-            QDesktopServices::openUrl(QUrl::fromEncoded(descrLink.toUtf8()));
++        const QString entryName = m_proxyModel->index(rowIndex.row(), 
SearchSortModel::NAME).data().toString();
++        const QString descrLink = m_proxyModel->index(rowIndex.row(), 
SearchSortModel::DESC_LINK).data().toString();
++
++        const QUrl descrLinkURL {descrLink};
++        if (descrLinkURL.isEmpty()) [[unlikely]]
++        {
++            if (warningEntryName.isEmpty())
++                warningEntryName = entryName;
++            ++emptyLinkCount;
++        }
++        else if (descrLinkURL.isLocalFile()) [[unlikely]]
++        {
++            if (badLinkCount == 0)
++                warningEntryName = entryName;
++            ++badLinkCount;
++
++            LogMsg(tr("Blocked opening search result description page URL. 
URL pointing to local file might be malicious behaviour. Name: \"%1\". URL: 
\"%2\".")
++                    .arg(entryName, descrLink), Log::WARNING);
++        }
++        else [[likely]]
++        {
++            QDesktopServices::openUrl(descrLinkURL);
++        }
++    }
++
++    if (badLinkCount > 0)
++    {
++        QString message = tr("Blocked opening search result description page 
URL. The following result URL is pointing to local file and it may be malicious 
behaviour:\n%1").arg(warningEntryName);
++        if (badLinkCount > 1)
++            message.append(u"\n" + tr("There are %1 more results with the 
same issue.").arg(badLinkCount - 1));
++        QMessageBox::warning(this, u"qBittorrent"_s, message, 
QMessageBox::Ok);
++    }
++    else if (emptyLinkCount > 0)
++    {
++        QString message = tr("Entry \"%1\" has no description page URL 
provided.").arg(warningEntryName);
++        if (emptyLinkCount > 1)
++            message.append(u"\n" + tr("There are %1 more entries with the 
same issue.").arg(emptyLinkCount - 1));
++        QMessageBox::warning(this, u"qBittorrent"_s, message, 
QMessageBox::Ok);
+     }
+ }
+ 
+--- a/src/gui/search/searchjobwidget.h
++++ b/src/gui/search/searchjobwidget.h
+@@ -127,7 +127,7 @@ private:
+     void onUIThemeChanged();
+ 
+     void downloadTorrents(AddTorrentOption option = 
AddTorrentOption::Default);
+-    void openTorrentPages() const;
++    void openTorrentPages();
+     void copyTorrentURLs() const;
+     void copyTorrentDownloadLinks() const;
+     void copyTorrentNames() const;
diff -Nru 
qbittorrent-5.1.0/debian/patches/9b29d37d210f28f46eb4758611d7b06f4603b9d1.patch 
qbittorrent-5.1.0/debian/patches/9b29d37d210f28f46eb4758611d7b06f4603b9d1.patch
--- 
qbittorrent-5.1.0/debian/patches/9b29d37d210f28f46eb4758611d7b06f4603b9d1.patch 
    1970-01-01 01:00:00.000000000 +0100
+++ 
qbittorrent-5.1.0/debian/patches/9b29d37d210f28f46eb4758611d7b06f4603b9d1.patch 
    2025-07-06 16:39:44.000000000 +0200
@@ -0,0 +1,37 @@
+From 9b29d37d210f28f46eb4758611d7b06f4603b9d1 Mon Sep 17 00:00:00 2001
+From: Chocobo1 <choco...@users.noreply.github.com>
+Date: Mon, 30 Jun 2025 01:39:03 +0800
+Subject: [PATCH] WebAPI: Trim leading whitespaces on Run External Program
+ fields
+
+Hacked qbt instances may contain malicious script placed in Run External 
Program and the script
+will attempt to hide itself by adding a lot whitespaces at the start of the 
command string.
+Users may mistake the field of being empty but is actually not.
+So trim the leading whitespaces to easily expose the malicious script.
+
+Note that GUI already trim the fields and only WebAPI doesn't trim them. This 
patch will unify
+the behavior.
+Related: 
https://github.com/qbittorrent/docker-qbittorrent-nox/issues/71#issuecomment-2993567440
+
+PR #22939.
+---
+ src/webui/api/appcontroller.cpp | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/src/webui/api/appcontroller.cpp
++++ b/src/webui/api/appcontroller.cpp
+@@ -673,12 +673,12 @@ void AppController::setPreferencesAction
+     if (hasKey(u"autorun_on_torrent_added_enabled"_s))
+         pref->setAutoRunOnTorrentAddedEnabled(it.value().toBool());
+     if (hasKey(u"autorun_on_torrent_added_program"_s))
+-        pref->setAutoRunOnTorrentAddedProgram(it.value().toString());
++        
pref->setAutoRunOnTorrentAddedProgram(it.value().toString().trimmed());
+     // Run an external program on torrent finished
+     if (hasKey(u"autorun_enabled"_s))
+         pref->setAutoRunOnTorrentFinishedEnabled(it.value().toBool());
+     if (hasKey(u"autorun_program"_s))
+-        pref->setAutoRunOnTorrentFinishedProgram(it.value().toString());
++        
pref->setAutoRunOnTorrentFinishedProgram(it.value().toString().trimmed());
+ 
+     // Connection
+     // Listening Port
diff -Nru qbittorrent-5.1.0/debian/patches/series 
qbittorrent-5.1.0/debian/patches/series
--- qbittorrent-5.1.0/debian/patches/series     1970-01-01 01:00:00.000000000 
+0100
+++ qbittorrent-5.1.0/debian/patches/series     2025-07-06 16:39:32.000000000 
+0200
@@ -0,0 +1,2 @@
+4f94eac235cefa8b83489cb3135dad87fcbed1e3.patch
+9b29d37d210f28f46eb4758611d7b06f4603b9d1.patch

--- End Message ---
--- Begin Message ---
Unblocked.

--- End Message ---

Reply via email to