https://bugs.kde.org/show_bug.cgi?id=520509
Bug ID: 520509
Summary: ksecretd silently corrupts binary secrets when
`content_type` starts with "text/"
Classification: Frameworks and Libraries
Product: frameworks-kwallet
Version First 6.24.0
Reported In:
Platform: Compiled Sources
OS: Linux
Status: REPORTED
Severity: normal
Priority: NOR
Component: general
Assignee: [email protected]
Reporter: [email protected]
CC: [email protected]
Target Milestone: ---
Created attachment 192531
--> https://bugs.kde.org/attachment.cgi?id=192531&action=edit
MRE
DESCRIPTION
ksecretd irreversibly corrupts binary secret values stored via
org.freedesktop.secrets when the secret's content_type starts with "text/".
Non-UTF-8 byte sequences are replaced with U+FFFD (0xEF 0xBF 0xBD), destroying
the data. Secrets stored with "application/octet-stream" are not affected.
Root cause: In KWalletFreedesktopItem::SetSecret
(src/runtime/ksecretd/kwalletfreedesktopitem.cpp), when
mimeType.startsWith("text/"), the value bytes are passed through
QString::fromUtf8() and stored as a KWallet password. QString::fromUtf8()
replaces invalid UTF-8 sequences with U+FFFD. On read-back via GetSecret, the
mangled data is returned.
The freedesktop Secret Service spec
(https://specifications.freedesktop.org/secret-service/latest-single/) defines
"value" as an array of bytes. The service must not interpret or transcode the
value based on content_type — it is metadata for clients only.
Real-world impact: Atlassian CLI (acli), Salesforce CLI, Zed editor, and any
app using go-keyring (which always sets content_type="text/plain;
charset=utf8") cannot store credentials on KDE.
STEPS TO REPRODUCE
1. Save the attached mre_ksecretd.py
2. Install deps: sudo apt install libdbus-1-dev libglib2.0-dev
3. Run: uv run mre_ksecretd.py (or: pip install dbus-python && python
mre_ksecretd.py)
OBSERVED RESULT
```
--- text/plain; charset=utf8 ---
Original: 83 bytes, hex: 1f8b08000000000002fff348cdc9c9d75128c9c8
Retrieved: 163 bytes, hex: 1fefbfbd08000000000002efbfbdefbfbd48efbf
Result: FAIL — 40 U+FFFD replacements
--- application/octet-stream ---
Original: 83 bytes, hex: 1f8b08000000000002fff348cdc9c9d75128c9c8
Retrieved: 83 bytes, hex: 1f8b08000000000002fff348cdc9c9d75128c9c8
Result: PASS
83 bytes stored, 163 bytes retrieved. Every non-UTF-8 byte replaced with 0xEF
0xBF 0xBD. Data irreversibly destroyed.
```
EXPECTED RESULT
Both content types should round-trip the secret value without modification. 83
bytes in, 83 identical bytes out.
SOFTWARE/OS VERSIONS
Operating System: Kubuntu 26.04 LTS
KDE Plasma Version: 6.6.4
KDE Frameworks Version: 6.24.0
Qt Version: 6.10.2
Kernel Version: 7.0.0-15-generic (64-bit)
ADDITIONAL INFORMATION
Suggested fix: When mimeType starts with "text/", validate that the byte array
is valid UTF-8 before passing to QString::fromUtf8(). If validation fails,
either fall back to Stream (binary) storage, or reject the operation with an
error (preferable to silent data corruption).
Related issues (same symptoms, no root cause identified):
- https://github.com/forcedotcom/cli/issues/2174 (Salesforce CLI — tokens
corrupted in KWallet)
- https://github.com/zed-industries/zed/issues/34024 (Zed editor — secrets not
readable from KWallet)
--
You are receiving this mail because:
You are watching all bug changes.