Skip to content

Release v1.7.0

Choose a tag to compare

@github-actions github-actions released this 06 Sep 16:56
· 37 commits to main since this release

Features

  • YubiKey OATH: TOTP and HOTP credentials stored on a YubiKey are listed, unlocked and read straight off the key, with live codes, the time left on the current one, touch prompts, and the panel following the key as it is plugged in and out. The card is reached through a PC/SC addon built in this repository (electron/native/pcsc): list readers, connect, transmit an APDU, transaction, disconnect, and nothing else. The OATH protocol itself is TypeScript, tested against recorded card responses
  • HOTP: counter-based one-time codes beside TOTP. The counter lives on the entry, generating a code advances it, and it can be stepped back and forward when a code is wasted. Import, export and the browser extension handle the format
  • Accessibility: everything is operable from the keyboard. The group tree, entry list and tab strips take arrow keys, Home/End and type-ahead, F6 cycles the panes, and dialogs trap focus and give it back on close. Every control has a role, a name and a state, toasts and search result counts are announced, the clipboard and one-time code timers have text alternatives, and a focus tooltip names the current selection. Windows High Contrast keeps selection and focus visible; animations stop when the OS asks for reduced motion. Verified with UI Automation on Windows and AT-SPI on Linux. The shortcut list is in Settings > General
  • Move entries and groups through a Move to group dialog, from a button or a shortcut. The confirmations that used to be OS message boxes are in-app dialogs, and a modal shown without the user asking for it no longer steals focus
  • External changes are merged as they arrive. A vault edited by another replica in a sync folder is merged and shown when the file lands, instead of at the next save
  • Conflict copies are picked up. The files sync clients leave beside a vault when two replicas write at once are found, offered, and absorbed into the open vault
  • Evicted iCloud vaults open again. With Optimize Mac Storage the bytes leave the disk and a .vault.kdbx.icloud placeholder takes their place, so the vault simply vanished from the start screen. The daemon is asked for the bytes and the open waits for them

Security

  • Windows Hello defaults to session scope, which is KeePassXC's only mode: a persistent blob is openable by same-user code behind one habituated prompt, and nothing the user did asked for that. Blobs written before the default changed are retired the first time the setting is read, and the DPAPI entropy is deleted with them, so one this misses cannot open either
  • AES-KDF has a ceiling of 100,000,000 rounds, checked on the header before the load starts. kdbxweb runs that KDF in the renderer through WebCrypto, where nothing can stop it once it is running, so a crafted file could hang the app; the Argon2 side already had a main-process gate. Every load of bytes from outside goes through the check: the unlock screen, a merge of the file on disk, a conflict copy
  • The HIBP lookup refuses redirects. The API key rides in a custom header, which fetch keeps across a cross-origin redirect (only Authorization is dropped), so a redirect from HIBP's edge would have handed the key to whatever host it named
  • The proxy token is only read from a file this user wrote and nobody else can read, checked on the open descriptor so the bytes read are the bytes checked, and it is written exclusively after removing whatever sat at the path, so a symlink planted there cannot receive it. The socket directory has to be private too: the Linux /tmp fallback and the macOS os.tmpdir() one are gone, and the socket itself is locked to the current user
  • The browser extension only gets a one-time code for an entry it was already given. get-totp names a uuid alone; a code is now served only for an entry get-logins released to that site in the last ten minutes. KeePassXC's per-entry browser options (hide entry, only-http-auth, not-http-auth, skip-auto-submit) are honoured
  • More Chromium switches are refused in packaged builds: --user-data-dir (whose granted-paths.json is arbitrary read and write grants), the four *-cmd-prefix and launcher switches that run a chosen binary as a child of the signed app, --load-extension, --disable-web-security, --js-flags, and the network ones that intercept or decrypt traffic (--proxy-server, --host-resolver-rules, --ignore-certificate-errors, --ssl-key-log-file)
  • Attachments are written owner-only and their names are reduced to a bare file name with no directories or control characters: a vault is shared data, so the name is whoever wrote the entry's choice
  • Backups taken before a master password change still open with the old password. The change now says so and offers to delete them
  • The channels that scan beside a vault are gated on the write grant only a vault path holds. Registering for external changes is too: it starts a directory watch that hashes the file for the renderer on every change, which ungated is a content-hash oracle for any file the user can read
  • SSH keys are taken out of the agent on quit, not only on window close, and the quit waits for the removals. Key file decryption is capped at a bounded number of KDF rounds
  • Only the pinned native binaries load. Argon2 is required from the pinned copy beside the app rather than the npm wrapper, packaging fails if the unpacked directory holds anything but those files plus the two addons built here, and dist-electron/native-manifest.json names each file, module, version, target and digest
  • The generator's length is clamped to 1-128 wherever it comes from: a cleared input used to persist as null and come back as a zero-length loop, and the extension's generate-password could be handed an empty string
  • Workflows get a read-only token by default, and the jobs holding signing secrets run in a release environment, so a required reviewer can stand between a tag push and the Apple certificate

Fixes

  • macOS: the browser extension stopped connecting after about three days. The proxy token sat in $TMPDIR, which dirhelper sweeps of anything not accessed for three days whether or not the app is running, and the token is written once at server start. It now lives in DARWIN_USER_CACHE_DIR, the location Apple names for exactly this
  • macOS: a vault in iCloud Drive, Desktop, Documents or Downloads saw nothing beside it. The open dialog grants the file without granting its folder, so conflict copies stayed invisible and the directory watch could not start. The folder is probed, the app can ask for it in an open dialog, and a directory that cannot be watched is polled instead
  • Touch ID: UTF-8 handling in the native addon. Byte order marks, lone continuation bytes, surrogates, overlong encodings and embedded NULs in account names are handled rather than trusted
  • Entries and groups could not be moved into the root group

Build and CI

  • libFuzzer targets for the native code, built with LLVM and run in the security workflow: the Touch ID account parser and the PC/SC length and buffer handling, each with a seed corpus
  • Fuzz tests for the IPC argument surface, generator settings, ssh-agent replies, the YubiKey OATH parser and TOTP