https://bugs.kde.org/show_bug.cgi?id=491898
--- Comment #9 from [email protected] --- Confirmed and root-caused from source (KDE/kwallet master; kf6-kwallet 6.18.0). Root cause: src/runtime/kwallet-query/src/querydriver.cpp, QueryDriver::writeValue(). It selects the write method from the entry's *existing* type: Wallet::EntryType kind = theWallet->entryType(entryName); if (kind == Wallet::Password) { ... writePassword ... } else if (kind == Wallet::Map) { ... writeMap ... } quit(); // exit 0 For a brand-new entry the key does not exist yet, so entryType() returns Wallet::Unknown (= 0). Neither branch matches Unknown, so no write is issued at all and control falls through to quit() -> exit 0 with no error. Overwriting an entry that already exists as Password/Map works; creating a new one silently does nothing. A direct org.kde.kwalletd6 writePassword() D-Bus call persists correctly because it has no such type gate. This is NOT an async / process-teardown race: the wallet is opened Asynchronous, but the write runs inside the walletOpened slot within the running event loop, and Wallet::writePassword() is a synchronous QDBusReply whose return code is checked. The write is simply never issued for new entries. Minimal repro: ls -la ~/.local/share/kwalletd/kdewallet.kwl kwallet-query -f login -w test_entry -v kdewallet <<< "test_value_123" # exits 0 ls -la ~/.local/share/kwalletd/kdewallet.kwl # size/mtime unchanged kwallet-query -f login -l kdewallet # test_entry absent The same write over qdbus-qt6 ... org.kde.KWallet.writePassword persists immediately. Fix (attached, git am / patch -p1 against master): default a new (Unknown) entry to a Password write. The patch also makes the tool fail with a non-zero exit instead of reporting a phantom success on an unwritable pre-existing type or invalid map JSON, and creates the target folder on demand instead of dropping the write when the folder does not exist yet. PATCH: >From 0017be0a524f8da22a67e080186b5e1f3f8cd44c Mon Sep 17 00:00:00 2001 From: Keeler <[email protected]> Date: Fri, 3 Jul 2026 12:05:00 +0000 Subject: [PATCH] kwallet-query: persist writes to new entries writeValue() picked the write method from the entry's *existing* type. entryType() returns Wallet::Unknown for an entry that does not exist yet, so for a brand-new entry neither the Wallet::Password nor the Wallet::Map branch ran: no write was issued and the tool still called quit() and exited 0. Creating a new secret with `kwallet-query -w` therefore silently did nothing, while overwriting an already-existing entry worked. A direct org.kde.kwalletd6 writePassword() D-Bus call persists correctly because it has no such type gate. Default a new (Unknown) entry to a Password write, matching writePassword(). While here, fail with a non-zero exit instead of reporting a phantom success when the entry is an unwritable pre-existing type or the map input is invalid JSON, and create the target folder on demand rather than dropping the write when the folder does not exist yet. BUG: 491898 --- src/runtime/kwallet-query/src/querydriver.cpp | 58 ++++++++++++++----- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/src/runtime/kwallet-query/src/querydriver.cpp b/src/runtime/kwallet-query/src/querydriver.cpp index de68d0d..67bada1 100644 --- a/src/runtime/kwallet-query/src/querydriver.cpp +++ b/src/runtime/kwallet-query/src/querydriver.cpp @@ -172,7 +172,17 @@ void QueryDriver::writeValue() if (verbose) { qDebug() << "writing" << entryName << "to" << entryFolder << "to" << walletName; } - theWallet->setFolder(entryFolder); + // setFolder() fails on a folder that does not exist yet, which would leave + // the write pointed at the wrong (or no) folder. Create it on demand and + // bail out loudly if we still cannot select it, instead of silently going on. + if (!theWallet->hasFolder(entryFolder)) { + theWallet->createFolder(entryFolder); + } + if (!theWallet->setFolder(entryFolder)) { + std::cout << i18n("The folder %1 does not exist!", entryFolder).toUtf8().constData() << std::endl; + exit(4); + return; + } QString passwordContents; for (std::string line; std::getline(std::cin, line);) { @@ -185,6 +195,13 @@ void QueryDriver::writeValue() } } Wallet::EntryType kind = theWallet->entryType(entryName); + // A brand-new entry does not exist yet, so entryType() reports Unknown. + // Previously neither branch below matched Unknown, so the write was silently + // dropped while the tool still exited 0 (bug 491898). Default new entries to + // Password, matching a direct writePassword() call over D-Bus. + if (kind == Wallet::Unknown) { + kind = Wallet::Password; + } if (kind == Wallet::Password) { if (verbose) { qDebug() << "about to write" << passwordContents; @@ -197,22 +214,31 @@ void QueryDriver::writeValue() } } else if (kind == Wallet::Map) { const QJsonDocument json = QJsonDocument::fromJson(passwordContents.toLatin1()); - if (!json.isNull()) { - QJsonObject values = json.object(); - QMap<QString, QString> map; - for (auto &e : values.keys()) { - map.insert(e, values.value(e).toString()); - } - if (verbose) { - qDebug() << "about to write" << map; - } - int rc = theWallet->writeMap(entryName, map); - if (rc != 0) { - std::cout << i18n("Failed to write entry %1 value to %2 wallet", entryName, walletName).toUtf8().constData() << std::endl; - exit(4); - return; - } + if (json.isNull()) { + std::cout << i18n("Failed to write entry %1 value to %2 wallet", entryName, walletName).toUtf8().constData() << std::endl; + exit(4); + return; + } + QJsonObject values = json.object(); + QMap<QString, QString> map; + for (auto &e : values.keys()) { + map.insert(e, values.value(e).toString()); + } + if (verbose) { + qDebug() << "about to write" << map; + } + int rc = theWallet->writeMap(entryName, map); + if (rc != 0) { + std::cout << i18n("Failed to write entry %1 value to %2 wallet", entryName, walletName).toUtf8().constData() << std::endl; + exit(4); + return; } + } else { + // Any other pre-existing type (e.g. Stream) is not writable here; fail + // rather than reporting a phantom success. + std::cout << i18n("Failed to write entry %1 value to %2 wallet", entryName, walletName).toUtf8().constData() << std::endl; + exit(4); + return; } quit(); } -- 2.43.0 -- You are receiving this mail because: You are watching all bug changes.
