From 9031cb530eabeb8ed463291dc5f018ff7e23068d Mon Sep 17 00:00:00 2001 From: Isaac Elliott Date: Mon, 3 Nov 2025 01:17:06 +1000 Subject: [PATCH] Allow read-only native message files (#12236) * Allow read-only native message files It's possible[^1] for a native message file to be both correct and read-only. When current versions of `keepassxc` encounter this, it fails, because it can't write to the file. In this situation it should only fail if the read-only file's contents are different to those it's trying to write. [^1]: e.g. when using an immutable OS management system like NixOS or home-manager. --------- Co-authored-by: Jonathan White --- src/browser/NativeMessageInstaller.cpp | 32 ++++++++++++++++++-------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/browser/NativeMessageInstaller.cpp b/src/browser/NativeMessageInstaller.cpp index b8beba7ad..bf0ad5aba 100644 --- a/src/browser/NativeMessageInstaller.cpp +++ b/src/browser/NativeMessageInstaller.cpp @@ -372,16 +372,30 @@ bool NativeMessageInstaller::createNativeMessageFile(SupportedBrowsers browser) QFile scriptFile(path); if (!scriptFile.open(QIODevice::WriteOnly)) { - qWarning() << "Browser Plugin: Failed to open native message file for writing at " << scriptFile.fileName(); - qWarning() << scriptFile.errorString(); - return false; + if (!scriptFile.open(QIODevice::ReadOnly)) { + qWarning() << "Browser Plugin: Failed to open native message file at " << scriptFile.fileName(); + qWarning() << scriptFile.errorString(); + return false; + } + + // We failed to write to `scriptFile`, but we can read it, so we assume that it's a read-only file. + // Consider success if the read-only file already contains the content we would have written. + QJsonDocument expectedDoc(constructFile(browser)); + QJsonDocument actualDoc = QJsonDocument::fromJson(scriptFile.readAll()); + + if (expectedDoc != actualDoc) { + qWarning() << "Browser Plugin: Unexpected (read-only) native message file at " << scriptFile.fileName(); + qWarning() << "Expected contents: " << expectedDoc; + return false; + } + } else { + QJsonDocument doc(constructFile(browser)); + if (scriptFile.write(doc.toJson()) < 0) { + qWarning() << "Browser Plugin: Failed to write native message file at " << scriptFile.fileName(); + qWarning() << scriptFile.errorString(); + return false; + } } - QJsonDocument doc(constructFile(browser)); - if (scriptFile.write(doc.toJson()) < 0) { - qWarning() << "Browser Plugin: Failed to write native message file at " << scriptFile.fileName(); - qWarning() << scriptFile.errorString(); - return false; - } return true; }