Bug 522615 - kwalletd6 Secret Service session memory leak causing exponential RSS growth and kernel OOM after prolonged use
Summary: kwalletd6 Secret Service session memory leak causing exponential RSS growth a...
Status: CONFIRMED
Alias: None
Product: frameworks-kwallet
Classification: Frameworks and Libraries
Component: general (other bugs)
Version First Reported In: 6.27.0
Platform: Arch Linux Linux
: NOR normal
Target Milestone: ---
Assignee: Valentin Rusu
URL:
Keywords:
: 522718 525331 (view as bug list)
Depends on:
Blocks:
 
Reported: 2026-07-04 13:19 UTC by AoyuJiao
Modified: 2026-09-20 17:48 UTC (History)
16 users (show)

See Also:
Latest Commit:
Version Fixed/Implemented In:
Sentry Crash Report:


Attachments
Forensic snapshot and full investigation report inside it (500.93 KB, application/x-xz)
2026-07-04 13:19 UTC, AoyuJiao
Details
Check whether a Secret Service provider registers the Prompt object it returns (4.41 KB, text/plain)
2026-08-08 14:58 UTC, Branislav Klocok
Details

Note You need to log in before you can comment on or make changes to this bug.
Description AoyuJiao 2026-07-04 13:19:50 UTC
Created attachment 194006 [details]
Forensic snapshot and full investigation report inside it

DESCRIPTION
After approximately 11 hours of uptime, kwalletd6's anonymous RSS grew from a normal baseline (~50 MB) to roughly 18.9 GB (anon-rss: 19,796,084 kB), exhausting the system's 32 GB of physical RAM plus 4 GB of swap. The Linux kernel OOM killer terminated kwalletd6 (PID 3911). systemd restarted it immediately and the system recovered. The restarted instance logs GTask "finalized without ever returning" warnings related to Secret Service prompt handling, suggesting the leak occurs in the D-Bus Secret Service code path.
Two attachments are provided with this report:
1. Full investigation report with complete evidence and analysis.
2. Forensic snapshot archive (14 MB compressed) containing OOM logs, complete journal, /proc snapshots, D-Bus traces, and a core dump of the running kwalletd6 instance for analysis.

STEPS TO REPRODUCE
1. Leave a KDE Plasma 6 session running with kwalletd6 D-Bus activated, Chrome (or other libsecret-using clients) running in the background.
2. Allow the system to remain idle or in light use for approximately 11+ hours.
3. Observe kwalletd6 RSS growth via system monitor. The leak rate is approximately 28 MB/minute once active. At ~18-19 GB RSS the kernel OOM killer will terminate kwalletd6.
Note: The issue is not fully reproducible on demand. See full report for conditions observed.

OBSERVED RESULT
- kwalletd6 anon-rss: 19,796,084 kB (~18.9 GB) at OOM kill time.
- file-rss: only 2,212 kB (negligible file-backed pages), confirming a pure heap leak, not file cache or shared memory.
- VIRT: 23,228,428 kB (~22.2 GB).
- systemd reported 18.9G memory peak and 2.9G swap peak.
- oom_score_adj: 200 (positive adjustment set by systemd for the dbus-activated unit).
- After OOM kill, the restarted kwalletd6 (PID 172592) logged:
    - "received unexpected result type ao from Completed signal instead of expected o"
    - "GTask secret_service_real_prompt_async ... finalized without ever returning (using g_task_return_*()). This potentially indicates a bug in the program."
- The OOM-killed instance (PID 3911) did not log these GTask warnings during its 11-hour lifetime, suggesting either a silent leak path or different code path was exercised.

EXPECTED RESULT
kwalletd6 should maintain a stable memory footprint of approximately 30-100 MB RSS regardless of uptime or Secret Service client activity.

SOFTWARE/OS VERSIONS
Operating System: Arch Linux (rolling), x86_64
KDE Plasma Version: 6.7.2-1
KDE Frameworks Version: (bundled in kwallet 6.27.0-1)
Qt Version: 6.11.1-1
Linux Kernel: 7.0.14-zen1-1-zen
Key packages:
  kwallet:        6.27.0-1
  glib2:          2.88.2-1
  libsecret:      0.21.7-1
  qca-qt6:        2.3.10-7
  xdg-desktop-portal:     1.22.1-2
  xdg-desktop-portal-kde: 6.7.2-1

ADDITIONAL INFORMATION
- systemd-oomd is verified disabled; this was the kernel OOM killer.
- Bug 490788 (QCA::Initializer destruction order, fixed in 6.23.0) shares the same code area (KWalletFreedesktopService/KWalletFreedesktopSessionAlgorithmDhAes) but causes a different symptom (crash on shutdown, not memory leak during operation). Our version 6.27.0 includes the fix, so this leak is a separate issue.
- Portal registration failure ("Could not register app ID") affects ALL KDE components equally on this installation -- it is systemic, not kwallet-specific, and therefore likely not the root cause.
- The signal type mismatch ("ao" vs "o" for the Completed signal) is a key lead: it causes the GLib GTask for the Secret Service prompt to never complete, potentially leaking the allocated task resources.
- Chrome (google-chrome 150.0.7871.46) is the most likely frequent caller of the Secret Service API during the observation period, but direct client-side evidence is not available in the current logs.
- Two files attached:
  (1) Forensic snapshot: kwalletd6_forensics_20260704_200709.tar.xz
  (2) Full investigation report inside the forensic snapshot: kwalletd6_memory_leak_bug_report.txt
Comment 1 zosima 2026-07-04 22:11:40 UTC
Reproduced, with a much faster leak rate, evidence tying it to the kwalletd6 -> ksecretd loop in bug 522307, and confirmation that downgrading pam_kwallet6 (per that bug's bisect) eliminates the problem.

SOFTWARE VERSIONS
OS: Fedora 44 (KDE spin), kernel 7.0.14-201.fc44.x86_64
Plasma: 6.7.1 (Wayland)
kf6-kwallet / kwalletd6: 6.27.0-1.fc44
pam-kwallet (pam_kwallet6): 6.7.1-1.fc44
Secret Service backend: ksecretd

OBSERVED
- kwalletd6 D-Bus-activated at 10:43:07 after a fresh boot + login (journalctl confirms zero suspend/resume events in the boot). OOM kill at 11:38:01 — so ~55 GB anon RSS in under 55 minutes, roughly 1 GB/min versus the ~28 MB/min in the original report. It exhausted 64 GB RAM plus most of an 8 GB swap.

- Kernel OOM record:
  Out of memory: Killed process 26948 (kwalletd6) total-vm:64172028kB, anon-rss:55416916kB, file-rss:5544kB, shmem-rss:0kB, UID:1000 pgtables:124492kB oom_score_adj:200

- systemd accounting for the unit:
  dbus-:1.2-org.kde.kwalletd6@0.service: Consumed 14min 11.211s CPU time over 54min 55.588s wall clock time, 53G memory peak, 7.7G memory swap peak.

- Same post-restart warnings as the original report:
  received unexpected result type ao from Completed signal instead of expected o
  g_task_return_error: assertion 'error != NULL' failed
  GTask secret_service_real_prompt_async (...) finalized without ever returning

- Additional failure face: ~50 minutes after the OOM respawn, the replacement kwalletd6 instance silently deadlocked — 0% CPU but no reply to any D-Bus call (even org.kde.KWallet.wallets timed out after 25 s), so every client (kwalletmanager, kded6 NM secret agent) failed with timeouts. Killing it and letting D-Bus respawn recovered. So the Secret Service client path in kwalletd6 can leak-loop OR deadlock depending on state.

- Link to bug 522307: for the entire window that kwalletd6 was growing, ksecretd (--pam-login) was spinning at ~32% CPU; the moment kwalletd6 was killed, ksecretd went fully idle. That report's dbus-monitor capture shows kwalletd6 calling ReadAlias("default") on ksecretd in a tight loop, and its reporter bisected the trigger to pam_kwallet6 6.7.1 — the version installed here.

CONFIRMED MITIGATION
Downgrading pam-kwallet to 6.6.4-1.fc44 (Fedora carries no 6.7.0) eliminates the issue: after reboot, ksecretd consumes zero CPU (previously ~32% from the first minute of the session) and kwalletd6 RSS stays flat at ~60 MB. This independently confirms the pam_kwallet6 6.7.1 bisect from bug 522307 on a second distribution.

Suggest cross-linking the two reports — 522307 (CPU loop) and this one (memory growth) look like two symptoms of the same defect.
Comment 2 AoyuJiao 2026-07-05 00:34:31 UTC
I’d like to clarify that the pam-kwallet version on my system is 6.7.2‑1, not 6.7.1. The memory leak is reproducible with this version as well, so the problem is not limited to the version initially mentioned in the bisect. Thanks.
Comment 3 zosima 2026-07-05 02:08:27 UTC
Data point: the leak recurred on my machine with pam-kwallet6 downgraded to 6.6.4 (retracting the mitigation I reported earlier on this bug and bug 522307). Different trigger shape this time - kwalletd6 was D-Bus-activated by a client 65 min after login (not at login), and RSS growth began immediately on activation.

Leak rate was far higher than in my original report: each kwalletd6 instance grew from ~60MB to 2.3-4.2GB in ~2-3 minutes (vs ~28MB/min previously), across 6 consecutive dbus-respawned instances (a >2GB watchdog killed each one), and the loop stopped permanently only when a pending Secret Service prompt was cancelled. Full timeline, journal correlates, and the prompt-path analysis in my comment today on bug 522307.

Versions at episode time: kf6-kwallet-6.27.0-1.fc44, pam-kwallet-6.6.4-1.fc44, Fedora 44, Plasma Wayland.
Comment 4 michaelk83 2026-07-05 09:45:54 UTC
(In reply to zosima from comment #3)
> the leak recurred on my machine with pam-kwallet6 downgraded to
> 6.6.4 (retracting the mitigation I reported earlier).

There are no significant code changes in pam-kwallet6 between 6.6.4 and 6.7.x (or even much further back), just version bumps and CI updates. So it wouldn't make sense for a downgrade of it to fix these two bugs.
https://invent.kde.org/plasma/kwallet-pam/-/compare/v6.6.4..v6.7.2?from_project_id=2562
https://invent.kde.org/plasma/kwallet-pam/-/network/master?ref_type=heads
Comment 5 michaelk83 2026-07-06 21:20:50 UTC
*** Bug 522718 has been marked as a duplicate of this bug. ***
Comment 6 Branislav Klocok 2026-07-21 01:42:08 UTC
Also reproducible on openSUSE Tumbleweed, so this is not distro-specific:

  openSUSE Tumbleweed, Wayland
  kwalletd6 6.28.0
  plasma6-nm 6.7.2, plasmashell 6.7.2
  Qt 6.11.1
  dbus-1 1.14.10
  kernel 7.1.3

THE WRITE ACTUALLY SUCCEEDS - ONLY ITS COMPLETION IS LOST

This seems worth highlighting, because it reframes the bug: it is not that saving the secret fails. After the loop had been running for hours I dumped the wallet directly:

  $ kwallet-query -l -f "Network Management" kdewallet
  ... 188 entries ...

  $ kwallet-query -r "{<uuid>};802-11-wireless-security" -f "Network Management" kdewallet
  (non-empty, contains the psk key, same structure as entries written before the regression)

So the data lands in the wallet correctly. What never arrives is the acknowledgement, which matches the "secret_service_real_prompt_async finalized without ever returning" backtrace and the "ao" vs "o" signature mismatch in the Completed signal. The client therefore never learns it succeeded and retries forever.

WHO IS RETRYING

A short "dbus-monitor --profile" capture (3 s, ~34k lines) shows kded6 - the plasma-nm secret agent - calling org.kde.KWallet.writePassword (plus open and networkWallet) on kwalletd6 at roughly 22 calls/second, while transient bus connections hit CreateItem / ReadAlias / Properties.GetAll / StartServiceByName on org.kde.secretservicecompat at the same rate. This also explains why killing ksecretd does not help: clients re-activate it immediately.

The item being rewritten is the PSK of the *currently active* wifi connection, with Created == Modified == now - it is continuously deleted and recreated. ksecretd signal serials advanced by >1.17M in ~34 minutes (~570 broadcasts/s), and kdewallet_attributes.json (85 KB) is rewritten constantly, producing an inotify storm.

TRIGGER AND USER-VISIBLE SYMPTOM

It starts when a *new* wifi network with a password is added. The giveaway is that the password prompt appears twice - first the inline prompt in the panel, then a separate dialog. That is the agent not knowing whether the first write went through.

It is intermittent, not every save - I have hit it only a handful of times over a long period, on an ordinary WPA2-PSK network (key-mgmt=wpa-psk, PMF disabled) with nothing to distinguish it from the ~90 other WPA2-PSK networks that saved fine. Open networks never trigger it, since nothing is written.

WORKAROUND THAT WORKS

  systemctl --user restart plasma-kded6.service

Because the entry is already in the wallet, the restarted agent finds it, has nothing to write, and the loop cannot re-ignite. Measured immediately after the restart:

                        during the loop            after restarting kded6
  kwalletd6 RSS         2.7 GB, +600 MB/min        15-20 MB, flat
  ksecretd CPU          ~22 % sustained            0 %
  MOVED_TO events       dozens per second          0
  CPU package temp      81 C                       49 C

The secret stays in the wallet; nothing needs to be moved out of it.

TWO NEGATIVE RESULTS THAT MAY SAVE OTHERS TIME

- "Close When Idle=true" in kwalletrc does NOT help. The loop itself generates hundreds of accesses per second, so the wallet is never idle and the timer never fires. Tried it: RSS still reached 2.7 GB and the OOM killer stepped in twice.

- Killing ksecretd appears to help but only because the wallet locks as a side effect. Once it is unlocked again the loop resumes. It also comes back without --pam-login, which breaks the automatic unlock for the rest of the session.

ONE MORE DATA POINT FOR THE ACCUMULATION THEORY

While the wallet was locked, kwalletd6 RSS dropped from 1.7 GB to 663 MB on its own, and resumed growing after unlocking. So the memory is reachable and tied to serving requests, which fits accumulating client-side async objects rather than a classic leak.

Happy to provide the full D-Bus capture or run further instrumentation if useful.
Comment 7 Emerald Dragon 2026-07-31 17:44:05 UTC
I am adding this report because my reproduction appears to match the reported kwalletd6 Secret Service memory leak, including recovery after restarting kwalletd6.

I believe I am experiencing the same issue described in this report on Fedora 44 KDE Plasma.

## System information

* Fedora Linux 44 KDE Plasma
* Plasma version: 6.7.3
* KDE Frameworks version: 6.28.0
* Qt version: 6.11.1
* Kernel: 7.1.5-200.fc44.x86_64
* Graphics platform: Wayland

Relevant packages:

```text
kf6-kwallet-6.28.0-1.fc44.x86_64
kf6-kwallet-libs-6.28.0-1.fc44.x86_64
kf5-kwallet-5.116.0-5.fc44.x86_64
kf5-kwallet-libs-5.116.0-5.fc44.x86_64
kwalletmanager5-26.04.3-1.fc44.x86_64
pam-kwallet-6.7.3-1.fc44.x86_64
signon-kwallet-extension-26.04.3-1.fc44.x86_64
```

Plasma packages are version:

```text
6.7.3-1.fc44.x86_64
```

## Symptoms

After a period of normal desktop use, kwalletd6 gradually enters a bad state.

Observed symptoms:

* Applications using stored secrets begin failing.
* NetworkManager fails to retrieve stored Wi-Fi credentials.
* D-Bus requests to kwalletd6 eventually time out.
* Secret Service-related errors appear continuously in the kwalletd6 journal.
* Restarting kwalletd6 temporarily restores normal operation.

## Before restart

The affected kwalletd6 process:

```text
PID     ELAPSED       %CPU   %MEM    RSS
24379   1-14:18:42    25.1   2.9     976924
```

At this point:

* `kwalletd6` still owns the D-Bus name.
* `ksecretd` is running and provides `org.freedesktop.secrets`.
* The Secret Service interface can enumerate the `kdewallet` collection.
* However, `kwalletd6` no longer responds to D-Bus calls.

Examples:

```text
busctl --user tree org.kde.kwalletd6

Failed to introspect object ...:
Connection timed out
```

and:

```text
busctl --user call org.kde.kwalletd6 ...
Call failed:
Connection timed out
```

## Secret Service state

`ksecretd` appears healthy.

`busctl --user tree org.freedesktop.secrets` returns:

```text
/org/freedesktop/secrets
  /collection/kdewallet
```

The collection contains items and reports:

```text
Label: kdewallet
Items: 15
Locked: true
```

This suggests the wallet database exists and the Secret Service layer is active, but kwalletd6 stops servicing requests.

## Journal messages

The following messages appear repeatedly:

```text
received unexpected result type ao from Completed signal instead of expected o

g_task_return_error: assertion 'error != NULL' failed

GTask secret_service_real_prompt_async finalized without ever returning
```

In addition, kwalletd6 emits a large number of Qt timer errors:

```text
QObject::killTimer(): Error: timer id 721424634 is not valid for object 0x7ffe5c882450 (KWalletD, ), timer has not been killed
QObject::killTimer(): Error: timer id 738201851 is not valid for object 0x7ffe5c882450 (KWalletD, ), timer has not been killed
QObject::killTimer(): Error: timer id 754979068 is not valid for object 0x7ffe5c882450 (KWalletD, ), timer has not been killed
...
```

These appear in a rapid sequence with increasing invalid timer IDs, all referencing the same `KWalletD` object.

## Recovery

Restarting kwalletd6 restores functionality:

```bash
systemctl --user restart 'dbus-:1.2-org.kde.kwalletd6@1.service'
```

After restart:

```text
PID     ELAPSED     %CPU   %MEM    RSS
58780   01:17       22.9   0.3     118784
```

D-Bus introspection works again:

```text
busctl --user tree org.kde.kwalletd6
```

returns:

```text
/MainApplication
/modules
  /modules/kwalletd5
  /modules/kwalletd6
/org/kde/kwalletd
```

The KWallet password prompt appears after restart, which is expected because the daemon's unlocked in-memory session is lost.

## Additional observation

The issue appears to recur after additional uptime. The restart is a temporary recovery, not a permanent fix.

The behavior appears consistent with a Secret Service session/prompt handling problem causing kwalletd6 resource growth and eventual loss of D-Bus responsiveness.
Comment 8 Tomasz C. 2026-08-08 00:37:32 UTC
Trigger found: name conflict over org.freedesktop.secrets with gnome-keyring

I hit this bug on Arch (Plasma 6.7.4, kwallet 6.28.0, libsecret 0.21.7) with
gnome-keyring 1:50.0 installed alongside. The trigger turned out to be
gnome-keyring-daemon owning the org.freedesktop.secrets D-Bus name. Once it was
out of the picture, the leak stopped and has not returned.

THE CORE ISSUE

gnome-keyring returns a Prompt object path but never creates the object:

    Unlock  ->  object path "/org/freedesktop/secrets/prompt/u1"

    Prompt.Prompt on that path:
      Error org.freedesktop.DBus.Error.UnknownMethod: No such object path

    Introspect /org/freedesktop/secrets/prompt:
      <node>            <- empty

The counter increments on each attempt (u1, u2, u3), so every request announces
a new prompt without ever registering it on the bus. A spec-compliant client
then waits forever for Completed -- which is exactly the

    GTask secret_service_real_prompt_async (...) finalized without ever returning
    received unexpected result type ao from Completed signal instead of expected o

pair seen on the kwalletd6 side. Starting gcr-prompter by hand makes it register
org.gnome.keyring.SystemPrompter and PrivatePrompter correctly and changes
nothing, so the fault is in the daemon itself, not in prompter availability.

WHY THIS ONLY SURFACED NOW

On this system gnome-keyring has been socket-activated since 2024 and caused no
trouble for years. Symptoms appeared only after KWallet moved to the kwalletd6 +
ksecretd split, where kwalletd6 itself acts as a Secret Service client. That
suggests gnome-keyring is not the cause here but merely exposes the new code
path -- and that a guard on the kwalletd6 side is the right place to fix it.

RESOLUTION

Either mask the daemon:

    systemctl --user mask --now gnome-keyring-daemon.service \
                               gnome-keyring-daemon.socket

or uninstall gnome-keyring entirely, which is what I ended up doing. Removal is
straightforward where dependents require the virtual org.freedesktop.secrets
provider rather than gnome-keyring by name, since kwallet provides it as well.
Note that ~/.local/share/keyrings/ survives removal but nothing is left that can
read it, so migrate any secrets you still need first.

Either way ksecretd takes over org.freedesktop.secrets. kwalletd6 went from
~900 MB/min growth at 95% CPU to a steady 57 MB at essentially zero CPU, and
D-Bus traffic dropped from ~50,000 to ~10 messages per 4 seconds.

WHAT DID NOT HELP

apiEnabled=false in kwalletrc, and unloading the kded networkmanagement module.
The latter came back after a plasma-kded6 restart and the loop still did not
reappear with gnome-keyring gone -- to me the strongest indication that the name
conflict is the culprit rather than the module.

QUICK CHECK FOR OTHERS

    dbus-send --session --print-reply --dest=org.freedesktop.DBus \
      /org/freedesktop/DBus org.freedesktop.DBus.GetConnectionUnixProcessID \
      string:org.freedesktop.secrets

If the returned PID belongs to gnome-keyring-daemon instead of ksecretd, this is
likely the same situation.

CAVEAT

This is a single environment and it need not explain every occurrence; reporters
on openSUSE or Fedora may not have gnome-keyring installed at all. Regardless,
a guard on the kwalletd6 side seems worth considering -- a timeout or a retry
limit while waiting for Completed -- so that a broken Secret Service
implementation on the other end cannot cause unbounded memory growth.
Comment 9 michaelk83 2026-08-08 10:11:23 UTC
(In reply to Tomasz C. from comment #8)
> The trigger turned out to be gnome-keyring-daemon owning the
> org.freedesktop.secrets D-Bus name. Once it was
> out of the picture, the leak stopped and has not returned.

Good find!

> gnome-keyring returns a Prompt object path but never creates the object:
>     Unlock  ->  object path "/org/freedesktop/secrets/prompt/u1"

The spec doesn't explicitly specify prompt paths (another part where it's incomplete), but I suspect it should have been a numeric ID: `.../1`, `.../2`, etc. But `/org/freedesktop/secrets/prompt` being empty is also wrong, I think.
https://specifications.freedesktop.org/secret-service/latest/object-paths.html

Regardles of KDE's side, this is worth reporting to GNOME Keyring, as this looks like a bug on their end, and possibly a regression.

> WHY THIS ONLY SURFACED NOW
> Symptoms appeared only after KWallet moved to the kwalletd6 +  ksecretd split

That split was done over a year ago, in KDE Frameworks 6.14. Yet the memory leak reports only appeared about a month ago. I can think of two possible reasons:

1. A recent regression in GNOME Keyring breaking their prompt creation.
2. A recent regression in kwalletd causing it to use the public org.freedesktop.secrets interface instead of its internal org.kde.secretservicecompat interface. Normally, kwalletd uses the internal interface to talk to ksecrted, unless ksecrted is explicitly disabled in kwalletrc.

> WHAT DID NOT HELP
> apiEnabled=false in kwalletrc

That simply disables the public API in ksecretd (leaving only its internal address).

> Regardless, a guard on the kwalletd6 side seems worth considering -- a timeout or
> a retry limit while waiting for Completed -- so that a broken Secret Service
> implementation on the other end cannot cause unbounded memory growth.

I think the key fix on kwalletd side is to make sure it's using its internal address as intended. But I agree that guarding the waits is also desirable.
Comment 10 Branislav Klocok 2026-08-08 14:48:40 UTC
Since comment #8 explicitly asks whether the gnome-keyring conflict explains every
occurrence, here is a data point from the openSUSE side where it does not, and the
difference may help narrow down the fix.

gnome-keyring is not installed at all on this system. org.freedesktop.secrets is owned
by KeePassXC with its FdoSecrets integration enabled, and ksecretd does not compete for
that name, because kwalletrc here contains:

    [org.freedesktop.secrets]
    apiEnabled=false

That is the same setting listed under "what did not help" in comment #8, and as comment
#9 explains, it leaves ksecretd with only its internal address. It matters here that it
was already in place well before the leak episode I described in comment #6 - I checked
that against my own session logs rather than trusting my memory, and that section of the
file was not touched during the incident. Its origin is unknown to me: I did not set it,
there is no system-wide kwalletrc under /etc/xdg or /usr/share/kf6, and the string
appears in the ksecretd binary but not in kwalletd6. The practical consequence is that
at the time of my episode nothing was contesting org.freedesktop.secrets - a third-party
provider simply held it uncontested - and the loop still happened.

To test hypothesis (2) from comment #9 I captured session bus traffic while driving
read-only wallet calls, with kwalletd6 as :1.26, ksecretd as :1.15 and KeePassXC as :1.47:

    mc  :1.26 -> org.kde.secretservicecompat  /org/freedesktop/secrets    Secret.Service.ReadAlias
    mc  :1.26 -> org.kde.secretservicecompat  /.../collection/kdewallet   DBus.Properties.Get
    mr  :1.15 -> :1.26                        (replies)

There was not a single message to :1.47, so kwalletd6 talks to ksecretd over the internal
name exactly as intended and is not wrongly reaching for the public interface on this
machine.

My notes from the incident itself say the looping traffic also went to
org.kde.secretservicecompat, with CreateItem, ReadAlias, Properties.GetAll and
StartServiceByName at the same rate as the kded6 writePassword calls I quantified in
comment #6 - the internal path again. I should be honest about how much weight that
carries: the raw capture lived in /tmp and is long gone, my journal no longer reaches
back that far, and my notes do not state outright that those transient connections
belonged to kwalletd6, though it is by far the most plausible candidate. Please treat it
as a recollection backed by written notes rather than evidence I can still produce on
request.

If it does hold, then the broken prompt completion can arise on the internal
kwalletd6 to ksecretd path with no foreign Secret Service provider involved at all, which
would make removing gnome-keyring a way to remove one trigger rather than the fix. It
also argues that the guard proposed at the end of comment #8 and echoed in #9, a timeout
or a retry limit while waiting for Completed, is worth having regardless of what sits on
the other end.

One further observation seems worth recording for other users, since KDE alongside
KeePassXC is a common pairing: KeePassXC has the same gap that comment #8 describes for
gnome-keyring, only more pronounced.

    busctl --user introspect org.freedesktop.secrets /org/freedesktop/secrets
      -> aliases, collection

    busctl --user introspect org.freedesktop.secrets /org/freedesktop/secrets/prompt
      -> No such object path '/org/freedesktop/secrets/prompt'

There is no prompt node at all, not even the empty one reported for gnome-keyring, and no
session node either, while ksecretd exposes aliases, collection and session. Anyone who
lets KeePassXC hold org.freedesktop.secrets while kwalletd6 does reach for the public name
should therefore expect the same hang.

As for the current state here, restarting the plasma-nm secret agent with
systemctl --user restart plasma-kded6.service, as described in comment #6, has held for
19 days: kwalletd6 sits at 26 MB and ksecretd at 30 MB, both at 0% CPU, the journal shows
no GTask, "finalized without ever returning" or "unexpected result type" lines, and a
watchdog checking RSS and the wallet inotify rate every minute has not fired once in over
3000 runs. I can capture the bus traffic properly if the loop comes back, and would
welcome direction on what would be most useful to record if it does.
Comment 11 Branislav Klocok 2026-08-08 14:54:57 UTC
Correcting myself on the last part of my previous comment: the claim about KeePassXC does
not hold, and I would rather retract it here than have anyone build on it.

I concluded there that KeePassXC never exposes /org/freedesktop/secrets/prompt or a
session node, and inferred the same failure mode described for gnome-keyring in comment
#8. The introspection output I quoted is real, but my reading of it was wrong, because the
measurement was: busctl opens a fresh D-Bus connection per invocation, and a Secret
Service session is bound to the client connection, so it was already gone by the time I
looked for it. Those nodes are created on demand rather than kept around, so their absence
on an idle system means nothing.

Repeating the test inside a single connection with dbus-python gives the opposite result:

    OpenSession returned  /org/freedesktop/secrets/session/0b937bc4...
      /org/freedesktop/secrets/session   -> exists
      the returned session path          -> exists, org.freedesktop.Secret.Session
      Session.Close()                    -> succeeds

So KeePassXC 2.7.12 registers the object properly, and its binary implements the Prompt,
Session and Collection interfaces. Please disregard my "same gap as gnome-keyring, only
more pronounced" sentence and the prediction that followed it - neither is supported.

To be precise about what remains open: I did not test the prompt path itself, which would
need the database locked so a client actually receives a prompt object path back, and I
have not done that. So this is not evidence that KeePassXC handles prompts correctly
either - it simply is not evidence of the opposite, which is what I wrongly suggested.

The rest of my previous comment stands: no gnome-keyring on this system, no contest over
org.freedesktop.secrets at the time of the episode, and kwalletd6 observed talking to
ksecretd over the internal name.
Comment 12 Branislav Klocok 2026-08-08 14:58:28 UTC
Created attachment 194986 [details]
Check whether a Secret Service provider registers the Prompt object it returns

Following up on the open point from my correction: I have now checked the prompt path
itself, and KeePassXC registers the object it hands back.

Lock() on the collection returns /org/freedesktop/secrets/prompt/<id>, and introspecting
that path on the same connection finds a real object carrying
org.freedesktop.Secret.Prompt. Unlock() returned "/" here because the database was already
unlocked, so the path I exercised was the one from Lock().

That is the opposite of what comment #8 reports for gnome-keyring, where the returned path
has nothing behind it, and it supports reading that as a bug on their side rather than
something inherent to being a non-KDE Secret Service provider.

One limitation worth stating: I did not carry the prompt through to completion, so I have
not observed the signature of KeePassXC's Completed signal - which is the part that
actually misbehaves in this bug. Only the registration of the prompt object was verified.

I am attaching the test script in case it is useful to anyone checking their own provider.
It has to hold a single D-Bus connection throughout, because busctl and dbus-send open a
fresh connection per call while these objects are bound to the client connection - which
is exactly what led me to the wrong conclusion I retracted above.
Comment 13 Branislav Klocok 2026-08-08 17:11:36 UTC
I went through the remaining paths systematically, and the result argues against the
objection I raised earlier, so it seems only fair to say so plainly.

In libsecret 0.21.7 the prompt is asked for a specific type in three places only:
secret-paths.c:1080 wants "ao" for lock and unlock, while :1684 and :1948 want "o" for
CreateCollection and CreateItem respectively. The "expected o, received ao" message can
therefore only come from the latter two - Unlock is ruled out by construction, and the
spec agrees, since Unlock and Lock both take and return arrays of object paths.

Measuring each of those against ksecretd over org.kde.secretservicecompat, on
kwalletd6 6.28.0:

    Lock / Unlock      prompt completes with "ao"   - matches what libsecret asks for
    CreateItem         unlocked collection -> prompt "/", no prompt at all
                       locked collection   -> org.freedesktop.Secret.Error.IsLocked
    CreateCollection   prompt /org/freedesktop/secrets/prompt/p2
                       Completed carries "o"        - matches

So ksecretd does not produce the mismatch on any path that libsecret types. That
undercuts what I wrote in my earlier comment, where I argued the loop on my machine must
have arisen on the internal kwalletd6 to ksecretd path with no foreign provider involved.
If ksecretd cannot generate that signature at all, then something else did, and the
name-conflict finding in comment #8 carries more weight than I gave it.

Three caveats, so this is not read as more than it is. I measured 6.28.0-1.2 while the
episode I reported happened on 6.28.0-1.1. I only exercised the three operations libsecret
types, not every path through the service. And my recollection about the looping traffic
going to the internal name cannot be re-checked, since that capture is gone - as I noted
when I first mentioned it.

Two small things that may be useful anyway. ksecretd numbers its prompts p1, p2 and
registers them, so the empty prompt node reported for gnome-keyring in comment #8 does
look like the odd one out. And CreateItem against a locked collection failing with
IsLocked rather than handing back an unlock prompt means that particular combination
cannot be where the mismatch enters, which I had assumed it might be.
Comment 14 Brian Cohen 2026-08-09 21:32:39 UTC
Adding a data point from openSUSE Tumbleweed that closely matches the plasma-nm/
kded6 retry loop described here — including the "new WiFi network" trigger —
with two details I haven't seen in this report or in bug 522307: the loop
occurred WITHOUT gnome-keyring installed, and the retried writePassword calls
alternated between TWO different PSK values, which turned out to be my mistyped
first attempt and the correct second attempt from the same join flow. It appears
every unacknowledged save request retries forever, not just the most recent one.

Environment:
- openSUSE Tumbleweed, Plasma 6.7.3, kf6-kwallet / kwalletd6 6.28.0,
  kwalletmanager 26.04.3, pam_kwallet6 6.7.3
- gnome-keyring NOT installed; ksecretd (started via --pam-login) owns
  org.freedesktop.secrets and org.kde.secretservicecompat
- Problem first appeared after upgrading to Plasma 6.7 / 6.7.1

I've had two episodes with different drivers:

Episode 1 (2026-07-31) — kwalletd6-driven, same pattern as bug 522307:
kwalletd6 called ReadAlias + CreateItem against ksecretd ~40/sec; each colliding
CreateItem minted a renamed "__0_" duplicate entry in the wallet; ~175
folderUpdated signals/sec; the kwalletmanager tray applet redrew on every signal
(1h28m accumulated CPU). Killing kwalletd6 stopped it; the respawned instance
stayed quiet.

Episode 2 (2026-08-09) — kded6-driven; killing kwalletd6 did NOT help:

Trigger: I connected to a new Wi-Fi network. I mistyped the password at the
first prompt, was re-prompted, entered it correctly, and connected successfully.
A few minutes later the CPU storm was underway.

Observed:
- dbus-monitor showed kded6 (plasma-nm secret agent) calling
  org.kde.KWallet.writePassword ~40-55/sec (277 calls in a 5s window), every
  call targeting the same entry:
    folder: "Network Management"
    key:    "{<connection-uuid>};802-11-wireless-security"
- Successive payloads ALTERNATED between the mistyped PSK and the correct one —
  i.e. both save requests from the join flow were being retried indefinitely,
  interleaved. Each call used a different wallet handle, with `open` /
  `networkWallet` calls at the same rate (the agent re-opened the wallet per
  write).
- kwalletd6 mirrored each write into ksecretd (SearchItems + CreateItem at the
  same rate), producing ~120-140 folderUpdated signals/sec sustained.
- Resource impact: kwalletd6 RSS grew to 7.7 GB; after I killed it, the fresh
  instance reached 8.1 GB within ~13 minutes while the loop continued. ksecretd
  sat at 20-30% CPU, kwalletmanager at 60-67%, CPU package temp 93 C.

What did NOT stop episode 2:
- Killing kwalletd6 (fresh D-Bus-activated instance immediately re-entered the
  loop)
- Unloading the kded networkmanagement module via
  org.kde.kded6.unloadModule("networkmanagement") — loadedModules confirmed it
  gone, but kded6 kept issuing writePassword at the same rate, so the agent
  object apparently survives module unload.

What DID stop it, instantly:
  systemctl --user restart plasma-kded6.service
folderUpdated went from ~1160/10s to 0/10s, and all three processes dropped to
0% CPU. (I then killed the bloated kwalletd6 once more purely to reclaim the
leaked RSS; it respawned clean and stayed quiet.)

Possibly relevant negative results: during episode 2 the user journal contained
NONE of the log messages mentioned in this report — no GTask "finalized without
ever returning", no "unexpected result type", no invalid-timer warnings, no
QWizard::field messages. Combined with gnome-keyring being absent, this suggests
the retry loop does not require the broken-Prompt-provider trigger — consistent
with the note that there's no defensive timeout even when the Secret Service
provider is functioning.

One user-visible consequence others may hit: since the last retry to land wins,
the wallet can end up storing the MISTYPED password even though the connection
succeeded (NetworkManager still held the correct one in memory), so the next
reconnect fails once and re-prompts.

Happy to provide exact package versions or re-capture dbus-monitor traces
(passwords redacted) if useful.
Comment 15 Branislav Klocok 2026-08-12 07:24:38 UTC
Confirming comment #14 from the other openSUSE side, and correcting something of my own
while I am at it.

The negative result Brian reports is the part I can back up. My episode in July was the
same shape as his second one - the loop driven by kded6 writePassword against the PSK of
the connection I had just joined, killing kwalletd6 not helping, and
systemctl --user restart plasma-kded6.service stopping it instantly. Checking my notes
from that night, I never recorded a single GTask "finalized without ever returning" or
"unexpected result type" line from my own journal either. I should be straightforward
about what that means for my earlier comment: when I wrote that my observations matched
that backtrace and the ao versus o signature mismatch, I was taking the explanation from
this report and applying it to my case, not reporting something I had measured. The
journal from that night has since rotated, so I cannot go back and check. Two openSUSE
machines showing this loop with none of those messages present seems worth stating
plainly.

There is one detail from my setup that neither of the other reports has, and it may help
separate the two failure modes. On my machine org.freedesktop.secrets is owned by neither
ksecretd nor gnome-keyring, but by KeePassXC, because kwalletrc here carries
apiEnabled=false under [org.freedesktop.secrets] and ksecretd therefore never claims the
public name. Brian has ksecretd owning it; the original reporters had gnome-keyring. All
three configurations produce the same kded6 retry loop, which suggests the loop does not
care who holds that name at all.

I also checked ksecretd against the three operations libsecret types a prompt for, as
described in my previous comment, and it answers correctly in every one of them. Taken
together with the absent log messages, my reading is that this report may be covering two
different problems: the Secret Service prompt leak in the original description, which
produces those GTask messages and appears to need a provider that mishandles prompts, and
the kded6 writePassword retry loop, which produces no such messages and happens with a
perfectly well-behaved provider. If that is right, then my objection in an earlier comment
about the loop not requiring a broken provider was closer to the mark than my own
follow-up gave it credit for - but it applies to the retry loop, not to the leak this bug
was opened about.

One small thing to add to Brian's observation about two passwords alternating. In my case
the password was asked for twice during the join - an inline prompt in the panel and then
a separate dialog - and the connection succeeded. Under his reading that would mean two
save requests were in flight from a single join flow, which fits, though I have no capture
left to confirm it.
Comment 16 Branislav Klocok 2026-08-12 18:59:08 UTC
A second episode on the same machine today, this time caught while it was happening,
which lets me answer the question about log messages properly rather than from memory.

The trigger was the same as in July: joining a new network at a hotel, where the password
was requested twice during the join. A few minutes later the loop was running. What it
looked like, from the wallet daemon side:

    16:01      5714 MOVED_TO events on kdewallet_attributes.json in that single minute
    16:01:56   kwalletd6 RSS 553 MB
    16:01:57   plasma-kded6 restarted, kwalletd6 killed, ~540 MB freed
    16:13      kwalletd6 39 MB and falling, dbus-monitor quiet (4 lines in 5 s)

That is roughly 300 MB per minute, which is the same order as the growth reported in
comment #14, and on a machine with 8 GB it would have reached the OOM killer within
minutes had nothing intervened.

The part I could not establish before is what the journal contained. Here is every
distinct message ksecretd and kwalletd6 produced in the twenty minutes around the episode,
by count:

    28572   got event "..." for entry "..." [file] "..."
    11428   -->got CREATE signal for "..." sub_entry= 0x0
        3   Structure: QMultiHash(...) / Default wallet: "..."
        1   Failed to register with host portal QDBusError(...)
        0   GTask / finalized without ever returning / unexpected result type

Zero across the whole user journal for the surrounding half hour. So this confirms what
Brian reported in comment #14, from a third configuration: the kded6 retry loop runs to
the point of exhausting memory without emitting any of the prompt or GTask diagnostics
this report was opened around. It also settles the caveat I raised in my previous comment
- I had said I could not verify my own case because the journal had rotated, and now I
can, on a fresh occurrence.

One detail consistent with Brian's reading that the agent reopens the wallet on every
write: the episode touched several different temporary files in the wallet directory, each
accumulating hundreds of MODIFY and ATTRIB events, rather than one file being rewritten.

The recovery in this case was automatic. After the July episode I put a small watchdog on
a one-minute systemd user timer that restarts plasma-kded6 when kwalletd6 RSS crosses a
threshold or the inotify rate on the wallet attribute file goes over 30 per minute. This
was its first real trigger in 23 days, and it cut the loop 56 seconds after the threshold
was crossed. I mention it because anyone hit by this repeatedly can contain the damage
without waiting for a fix, and I am happy to attach the script if that is useful.

No lasting damage to the wallet here: no renamed duplicate entries of the kind described
in the first episode of comment #14, entry count up by the expected amount for one new
network, and the connection works normally.
Comment 17 kdeidentity 2026-08-20 16:58:05 UTC
(In reply to Branislav Klocok from comment #16)
> A second episode on the same machine today, this time caught while it was
> happening,
> which lets me answer the question about log messages properly rather than
> from memory.
> 
> The trigger was the same as in July: joining a new network at a hotel, where
> the password
> was requested twice during the join. A few minutes later the loop was
> running. What it
> looked like, from the wallet daemon side:
> 
>     16:01      5714 MOVED_TO events on kdewallet_attributes.json in that
> single minute
>     16:01:56   kwalletd6 RSS 553 MB
>     16:01:57   plasma-kded6 restarted, kwalletd6 killed, ~540 MB freed
>     16:13      kwalletd6 39 MB and falling, dbus-monitor quiet (4 lines in 5
> s)
> 
> That is roughly 300 MB per minute, which is the same order as the growth
> reported in
> comment #14, and on a machine with 8 GB it would have reached the OOM killer
> within
> minutes had nothing intervened.
> 
> The part I could not establish before is what the journal contained. Here is
> every
> distinct message ksecretd and kwalletd6 produced in the twenty minutes
> around the episode,
> by count:
> 
>     28572   got event "..." for entry "..." [file] "..."
>     11428   -->got CREATE signal for "..." sub_entry= 0x0
>         3   Structure: QMultiHash(...) / Default wallet: "..."
>         1   Failed to register with host portal QDBusError(...)
>         0   GTask / finalized without ever returning / unexpected result type
> 
> Zero across the whole user journal for the surrounding half hour. So this
> confirms what
> Brian reported in comment #14, from a third configuration: the kded6 retry
> loop runs to
> the point of exhausting memory without emitting any of the prompt or GTask
> diagnostics
> this report was opened around. It also settles the caveat I raised in my
> previous comment
> - I had said I could not verify my own case because the journal had rotated,
> and now I
> can, on a fresh occurrence.
> 
> One detail consistent with Brian's reading that the agent reopens the wallet
> on every
> write: the episode touched several different temporary files in the wallet
> directory, each
> accumulating hundreds of MODIFY and ATTRIB events, rather than one file
> being rewritten.
> 
> The recovery in this case was automatic. After the July episode I put a
> small watchdog on
> a one-minute systemd user timer that restarts plasma-kded6 when kwalletd6
> RSS crosses a
> threshold or the inotify rate on the wallet attribute file goes over 30 per
> minute. This
> was its first real trigger in 23 days, and it cut the loop 56 seconds after
> the threshold
> was crossed. I mention it because anyone hit by this repeatedly can contain
> the damage
> without waiting for a fix, and I am happy to attach the script if that is
> useful.
> 
> No lasting damage to the wallet here: no renamed duplicate entries of the
> kind described
> in the first episode of comment #14, entry count up by the expected amount
> for one new
> network, and the connection works normally.

Confirmed on OpenSUSE Tumbleweed. Happens indeed after joining a new wifi, where I get a second prompt for the password. About 20 to 30 minutes later, kwalletd6 is using 18+GB of RAM and machine crashes.
Comment 18 TraceyC 2026-08-20 23:18:47 UTC
*** Bug 524500 has been marked as a duplicate of this bug. ***
Comment 19 Nicolas Fella 2026-08-31 15:48:15 UTC
https://invent.kde.org/frameworks/kwallet/-/commit/068d7d07ad4fa2ce126cc9565c39529926d58c93 fixes some memory leaks in kwalletd6, can you please retest with 6.30 once that is released?
Comment 20 Nico 2026-09-02 08:33:35 UTC
For the time being, while waiting for the upstream fix to reach distribution packages, I set up a systemd user timer as a containment workaround.

It checks kwalletd6's anonymous memory once per minute. At 256 MiB it displays a persistent notification with a "Restart KWallet" button, which restarts the daemon to reclaim the leaked memory.

The monitor script, systemd service, timer, and installation instructions are here:

https://gist.github.com/D3SOX/35cb7d112661b99259496259a4a61c27

The monitor can be removed once the fixed KWallet version is installed.
Comment 21 kdeidentity 2026-09-02 10:06:41 UTC
(In reply to Nico from comment #20)
> For the time being, while waiting for the upstream fix to reach distribution
> packages, I set up a systemd user timer as a containment workaround.
> 
> It checks kwalletd6's anonymous memory once per minute. At 256 MiB it
> displays a persistent notification with a "Restart KWallet" button, which
> restarts the daemon to reclaim the leaked memory.
> 
> The monitor script, systemd service, timer, and installation instructions
> are here:
> 
> https://gist.github.com/D3SOX/35cb7d112661b99259496259a4a61c27
> 
> The monitor can be removed once the fixed KWallet version is installed.

Lol, I was a bit more drastic and just added a cron entry that kills kwalletd6 every 2 minutes. There is no real consequence, it just restarts itself, which is totally fine.
Comment 22 michaelk83 2026-09-07 09:00:13 UTC
*** Bug 525331 has been marked as a duplicate of this bug. ***
Comment 23 vindicator 2026-09-07 20:14:32 UTC
For those manually or using a timer to kill off kwallet, might I suggest looking at `cgroups`, specifically `MemoryMax=<#>` for systemd units, where the process is killed when that threshold has been reached.

It can't be done with a simple "systemctl edit --user" command though.
Unit: dbus-:<#>.<#>-org.kde.kwalletd@<#>.service
1) $ systemctl status --user <...> //get the current transient iteration. start with "dbus" and double-tab for bash-completion to list out what exists.
2) $ cat <...> //display contents of the unit file in path from the status output
3) $ systemctl edit --user --full --force <...> //normally nice with regular unit files, but not transients. ***Need to strip out ":<#>.<#>" and "@<#>" (but keep the "@" itself)
4) copy/paste contents from "cat"
5) add "MemoryMax=<#>" under the "[Service]" section. <#>="1G" for example if you want to be generous.
6) systemctl stop --user <unit> //just to kill existing transient so override can take effect with the next iterative run.

This is partly pseudo. I haven't tried it for this service, but have used cgroups in general successfully.
Comment 24 Xinyu Tu 2026-09-08 02:34:38 UTC
Some observations from local debugging:
I've been tracking this memory growth locally and wanted to share a few observations regarding how these components interact during this state:

1: kwalletd6 behavior: It acts as a passive, event-driven daemon handling incoming D-Bus requests. The rapid memory growth (~14 MB/s RSS in my environment) appears to be a downstream effect driven by an unusually high volume of incoming traffic—specifically continuous CreateItem and GetProperties requests for org.freedesktop.Secret.Item.Attributes.

2: Client-side request frequency: Monitoring D-Bus traffic indicates that plasma-nm (inside kded6) enters a high-frequency retry/polling loop under specific conditions (such as syncing a specific Wi-Fi credential UUID like {...};802-11-wireless-security).

3: Cascade effect: When this loop triggers at ~10ms intervals, session and proxy objects are instantiated faster than the standard lifecycle cleanup can process them, leading to high CPU load in kded6 and steady RSS growth in kwalletd6.
Comment 25 Branislav Klocok 2026-09-20 14:36:48 UTC
Retested on 6.30.0 as asked in comment #19. Three runs today, all clean, but I want to be
upfront about what that does and does not show.

Setup: openSUSE Tumbleweed, kwalletd6 and kf6-kwallet 6.30.0 installed on 13 September,
Plasma on Wayland. Rather than waiting for this to happen on its own I triggered it
deliberately with a phone hotspot, since joining a new password-protected network is what
started it for me in July and again in August. I sampled kwalletd6 and ksecretd RSS, kded6
CPU and the rate of org.kde.KWallet.writePassword calls every two seconds throughout.

The first run was a plain join with the correct password on the first try. Fifteen minutes,
395 samples: kwalletd6 went up by 1.4 MB once as the secret was written and then stayed
flat, with no writePassword traffic at all afterwards.

The third run is the interesting one, because it reproduces the sequence from comment #14
exactly. I deliberately mistyped the password, got a second prompt, entered the correct one
and connected. NetworkManager logged both secret requests from that single join:

    secrets required            first prompt, wrong password
    secrets exist               second prompt, correct password
    Activation: successful, device activated

Eleven minutes after that connection: kwalletd6 grew by 20 kB in total, writePassword
stayed at 0/s across 77 separate measurements, kded6 sat at 0.0% CPU, and no GTask or
"unexpected result type" lines appeared. For comparison, in July this machine was losing
roughly 600 MB per minute at this point, and in August I measured 553 MB in under two
minutes with 5714 inotify events on the wallet attribute file in a single minute.

Now the caveat, which matters more than the numbers. This bug has always been intermittent
for me. Over the years I hit it a handful of times, not on every network I joined, so the
overwhelming majority of joins were always quiet even before your fix. Three clean runs are
therefore a good sign and nothing more. I cannot tell you the leak is gone, only that I
could not provoke it today along the path that provoked it twice before.

I will keep the RSS watchdog running and will report back if it ever fires again, which is
probably the more useful signal over the next few weeks of travelling.

One unrelated thing I ran into while setting this up, in case it is useful to someone. On a
WPA3/SAE network a wrong password leaves the profile permanently stuck: NetworkManager
reports that secrets exist, retries the stored one, fails, and never asks the agent for a
new one, so there is no way to correct it from the applet. On WPA2-PSK the second prompt
appears normally. The wrong password also gets written to the wallet even when the
connection fails, which lines up with what was reported in comment #14 about the mistyped
password winning.