From e43dcb8f6eeccf8521d79f5f08cae81cd2331758 Mon Sep 17 00:00:00 2001 From: Rello Date: Fri, 17 Apr 2026 12:36:51 +0200 Subject: [PATCH 1/4] fix: improve socket validation Signed-off-by: Rello --- src/gui/socketapi/socketapi.cpp | 77 ++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/src/gui/socketapi/socketapi.cpp b/src/gui/socketapi/socketapi.cpp index 496a2a4d10131..5d373733b3b75 100644 --- a/src/gui/socketapi/socketapi.cpp +++ b/src/gui/socketapi/socketapi.cpp @@ -65,6 +65,10 @@ #include #include +#ifdef Q_OS_WIN +#include +#endif + #ifdef Q_OS_MACOS #include #include "common/utility_mac_sandbox.h" @@ -106,6 +110,63 @@ QStringList split(const QString &data) return data.split(RecordSeparator()); } +#ifdef Q_OS_WIN +bool isTrustedWindowsPipeClient(QIODevice *socket, QString *errorDetails = nullptr) +{ + auto *localSocket = qobject_cast(socket); + if (!localSocket) { + if (errorDetails) { + *errorDetails = QStringLiteral("socket is not a QLocalSocket"); + } + return false; + } + + const auto socketDescriptor = localSocket->socketDescriptor(); + if (socketDescriptor == -1) { + if (errorDetails) { + *errorDetails = QStringLiteral("invalid socket descriptor"); + } + return false; + } + + ULONG clientProcessId = 0; + if (!GetNamedPipeClientProcessId(reinterpret_cast(socketDescriptor), &clientProcessId)) { + if (errorDetails) { + *errorDetails = QStringLiteral("GetNamedPipeClientProcessId failed: %1").arg(GetLastError()); + } + return false; + } + + DWORD currentSessionId = 0; + if (!ProcessIdToSessionId(GetCurrentProcessId(), ¤tSessionId)) { + if (errorDetails) { + *errorDetails = QStringLiteral("ProcessIdToSessionId failed for current process: %1").arg(GetLastError()); + } + return false; + } + + DWORD clientSessionId = 0; + if (!ProcessIdToSessionId(clientProcessId, &clientSessionId)) { + if (errorDetails) { + *errorDetails = QStringLiteral("ProcessIdToSessionId failed for client process %1: %2").arg(clientProcessId).arg(GetLastError()); + } + return false; + } + + if (clientSessionId != currentSessionId) { + if (errorDetails) { + *errorDetails = QStringLiteral("client process %1 is in session %2, expected session %3") + .arg(clientProcessId) + .arg(clientSessionId) + .arg(currentSessionId); + } + return false; + } + + return true; +} +#endif + #if GUI_TESTING using namespace OCC; @@ -299,7 +360,11 @@ SocketApi::SocketApi(QObject *parent) } } - const bool result = _localServer.listen(socketPath); + if (Utility::isWindows()) { + _localServer.setSocketOptions(QLocalServer::UserAccessOption); + } + + const bool result = _localServer.listen(socketPath); qCDebug(lcSocketApi) << "Full server name:" << _localServer.fullServerName(); if (result) { @@ -340,6 +405,16 @@ void SocketApi::slotNewConnection() if (!socket) { return; } + +#ifdef Q_OS_WIN + QString trustError; + if (!isTrustedWindowsPipeClient(socket, &trustError)) { + qCWarning(lcSocketApi) << "Rejecting untrusted SocketAPI client:" << trustError; + socket->deleteLater(); + return; + } +#endif + qCDebug(lcSocketApi) << "New connection" << socket; connect(socket, &QIODevice::readyRead, this, &SocketApi::slotReadSocket); connect(socket, SIGNAL(disconnected()), this, SLOT(onLostConnection())); From 5ab0b4df3958ba36922d883b7322304e321cd3a8 Mon Sep 17 00:00:00 2001 From: Rello Date: Fri, 17 Apr 2026 12:39:09 +0200 Subject: [PATCH 2/4] Fix indentation in socketapi.cpp Signed-off-by: Rello --- src/gui/socketapi/socketapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/socketapi/socketapi.cpp b/src/gui/socketapi/socketapi.cpp index 5d373733b3b75..cbebc6cf9031f 100644 --- a/src/gui/socketapi/socketapi.cpp +++ b/src/gui/socketapi/socketapi.cpp @@ -364,7 +364,7 @@ SocketApi::SocketApi(QObject *parent) _localServer.setSocketOptions(QLocalServer::UserAccessOption); } - const bool result = _localServer.listen(socketPath); + const bool result = _localServer.listen(socketPath); qCDebug(lcSocketApi) << "Full server name:" << _localServer.fullServerName(); if (result) { From 25929e17f7c0b7d60f5a1136791d2bc053c276eb Mon Sep 17 00:00:00 2001 From: Matthieu Gallien Date: Fri, 17 Apr 2026 14:22:37 +0200 Subject: [PATCH 3/4] fix(share): ask for confirmation before leaving a share there is no way to undo leaving a share. Better ask users for confirmation Signed-off-by: Matthieu Gallien --- src/gui/folderman.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/gui/folderman.cpp b/src/gui/folderman.cpp index ae388eb8d412a..48fe5e2d2c341 100644 --- a/src/gui/folderman.cpp +++ b/src/gui/folderman.cpp @@ -1783,6 +1783,16 @@ void FolderMan::setDirtyNetworkLimits(const AccountPtr &account) const void FolderMan::leaveShare(const QString &localFile) { const auto localFileNoTrailingSlash = localFile.endsWith('/') ? localFile.chopped(1) : localFile; + + QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::No; + + const auto message = tr("Are you sure to want to leave share %1?").arg(Utility::escape(localFileNoTrailingSlash)); + const auto result = QMessageBox::question(nullptr, tr("Confirm share leave"), message, buttons); + if (result == QMessageBox::No) { + qCDebug(lcFolderMan()) << "user canceled leaving share" << localFile; + return; + } + if (const auto folder = FolderMan::instance()->folderForPath(localFileNoTrailingSlash)) { const auto filePathRelative = Utility::noLeadingSlashPath(QString(localFileNoTrailingSlash).remove(folder->path())); From 5b141cbcd1548339874356a50464ba3c03c32a06 Mon Sep 17 00:00:00 2001 From: Rello Date: Mon, 20 Apr 2026 14:50:12 +0200 Subject: [PATCH 4/4] Update socketapi.cpp Signed-off-by: Rello --- src/gui/socketapi/socketapi.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/gui/socketapi/socketapi.cpp b/src/gui/socketapi/socketapi.cpp index cbebc6cf9031f..314b3377dda26 100644 --- a/src/gui/socketapi/socketapi.cpp +++ b/src/gui/socketapi/socketapi.cpp @@ -407,6 +407,14 @@ void SocketApi::slotNewConnection() } #ifdef Q_OS_WIN + // SECURITY NOTE: + // This is the central trust boundary for incoming Windows SocketAPI clients. + // We gate new connections here (before listener registration and command + // dispatch) using named-pipe client process/session validation. + // + // This check improves local IPC hardening but is not a complete security + // boundary against a fully compromised same-user environment. Command-level + // validation and user interaction requirements remain important. QString trustError; if (!isTrustedWindowsPipeClient(socket, &trustError)) { qCWarning(lcSocketApi) << "Rejecting untrusted SocketAPI client:" << trustError;