Skip to content

SSH agent: after the database file is reloaded from disk, lock no longer removes keys and unlock no longer adds them #13704

Description

@underclockeddev

Have you searched for an existing issue?

  • Yes, I tried searching and reviewed the pinned issues

Brief Summary

If the open database file changes on disk (edited by another program, or synced from another machine) and KeePassXC reloads it, the SSH agent integration stops working for that database until KeePassXC is restarted:

  • locking the database leaves its keys in the agent, even with "Remove key from agent when database is closed/locked" ticked
  • after clearing the agent, unlocking the database does not add them back, and no error is shown

This bites anyone who keeps a synced database open on two machines: every save on one breaks the other until restart.

Steps to Reproduce

  1. Enable SSH Agent integration. Create an entry with an SSH key and tick both "Add key to agent when database is opened/unlocked" and "Remove key from agent when database is closed/locked".
  2. Unlock the database. ssh-add -l lists the key.
  3. With the database still unlocked, change the file from outside KeePassXC, for example keepassxc-cli edit db.kdbx entry --notes x. KeePassXC reloads it.
  4. Lock the database. ssh-add -l still lists the key.
  5. Run ssh-add -D, then unlock the database again. The key is not added.

Expected Versus Actual Behavior

Expected: step 4 removes the key and step 5 adds it back, as they do without the reload.

Actual: The key stays in the agent after lock, and is not re-added on unlock. Restarting KeePassXC restores normal behaviour.

Cause

SSHAgent records which database added each key by Database::uuid(), and that uuid is generated per Database object. A reload (DatabaseWidget::reloadDatabaseFile() → replaceDatabase()) replaces the object, so the uuid changes and the agent's record still points at the old one:

  • SSHAgent::databaseLocked() looks for the new uuid, finds nothing, removes nothing.
  • SSHAgent::addIdentity() finds the key owned by the old uuid and refuses with "Key identity ownership conflict". databaseUnlocked() suppresses that error because the key is already known, so nothing is shown.

With a hardware key, the same thing happens when the reload asks for the key and the user presents it.

KeePassXC Debug Information

KeePassXC - Version 2.7.12
Revision: 860e51d

Qt 5.15.19
Debugging mode is disabled.

Operating system: EndeavourOS
CPU architecture: x86_64
Kernel: linux 7.2.6-arch2-1

Enabled extensions:
- Auto-Type
- Browser Integration
- Passkeys
- SSH Agent
- KeeShare
- YubiKey
- Secret Service Integration

Cryptographic libraries:
- Botan 3.13.0

Also reproduced on current develop (9e0f57a, 2.8.0-beta1).

Operating System

Linux

Linux Desktop Environment

KDE Plasma 6.7.5

Linux Windowing System

Wayland

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions