Keybay on Linux

Browse documentation

The ordinary desktop profile uses the user’s Secret Service keyring. The separate Flatpak candidate adds a sandbox-bound portal path.

Protection at a glance

  • Key access: an item in the user’s unlocked Secret Service provider. The application’s declared namespace is not an OS-authenticated identity.
  • File isolation: private directories and files restrict other users, but do not isolate programs running under the same user account.
  • Hardware assurance: no hardware-backed key guarantee from Secret Service.
  • Additional methods: a passphrase or hardware passkey is recommended for high-value records; any one enrolled method plus the platform root is required.
  • Main limitation: another authorized same-user program may reach the root and encrypted file. It may also delete or replace them.

This is a key-access level, not a hardware rating or protection against a compromised host process. See security levels for the exposure per attacker.

Requirements

Use an available session D-Bus and Secret Service provider with an unlocked default collection. The ordinary executable declares its namespace in its owning pubspec or embeds it with keybay_compile. Keybay does not unlock or create a keyring on your behalf, and headless environments without the required provider fail closed.

Ordinary desktop profile

An unsandboxed Dart executable declares its stable namespace in the owning pubspec or embeds it with keybay_compile. Keybay stores one encrypted framed file beneath ${XDG_DATA_HOME:-~/.local/share} in an identity-derived private directory. One identity-derived Secret Service item holds the platform root; record values do not become separate keyring items.

The file hierarchy and fixed live/stage/lock names are handled with descriptor-relative no-follow operations. Keybay creates 0700 directories and 0600 files, pins reader generations, locks mutations, fsyncs staged state, and atomically replaces the live file.

Keybay speaks the Secret Service D-Bus protocol directly through exact-pinned package:dbus. It never calls Unlock, Prompt, or CreateCollection. A locked item, prompt path, absent default collection, timeout, or late reply is a typed failure rather than a new empty store. Provider-specific access-control UI is outside the protocol’s prompt-object mechanism: root acquisition therefore requires allowed interaction. Only open, authentication changes and reset acquire the provider. Record operations and authentication listing never do.

First creation is insert-only and runs under a fixed provider lock in private XDG_RUNTIME_DIR; a racing initializer adopts only the exact authenticated winner. Reset deletes only the already-derived item and file state. Secret Service has no atomic compare-and-delete, so a same-user actor may still race reset as denial of service.

Limitations

This profile is namespaceOnly. Secret Service attributes do not authenticate the declaring application, so another authorized same-user process may claim the same namespace and reach the root item; it may also modify the user’s files. Authenticated encryption detects modification but cannot stop deletion. The Secret Service specification leaves additional access-control policy to the provider; lookup attributes are not authenticated application identities.

Add a Keybay passphrase or hardware passkey for passwords and high-value credentials. Either method prevents the Secret Service root item and encrypted file alone from yielding the store key. It cannot defend plaintext already returned to a compromised process or prevent same-user denial of service.

The shared threat model also excludes root/kernel compromise, keylogging, plaintext after disclosure and rollback.

Recovery

A locked or unavailable keyring is an access failure, not an empty store. Restore access to the existing provider and retry. If required key material is lost and the data is intentionally abandoned, Keybay.reset() is the explicit destructive recovery. It cannot reconstruct lost values. Do not create another root or switch providers to conceal the failure.

Qualification

The retained real-provider evidence uses gnome-keyring in a disposable D-Bus session. It does not claim to qualify every Secret Service implementation. Current source applicability is recorded in the qualification report.

Flatpak candidate

App-bound key · SDK candidate

  • Key access: the Secret Portal supplies an application secret for the authenticated sandbox caller.
  • File isolation: the Flatpak’s private data directory under the documented confinement and filesystem-grant constraints.
  • Hardware assurance: provider-managed secret; no hardware-backing claim.
  • Additional methods: the same alternative-method policy applies alongside the portal-derived root; hardware access also needs sandbox device permissions and separate qualification.
  • Main limitation: the key is app-bound only against other sandboxed apps. With GNOME Keyring, the portal keeps each app’s secret as an ordinary keyring item, so unsandboxed programs running as you can reach it and the app’s data directory; enroll a passphrase or passkey against them. Broad host grants can weaken confinement, and the portal secret survives Keybay reset, so restoring an old store can restore access.

This level is conditional on the confinement below. Candidate status and qualification are separate from the key-access label; Flatpak CLI packaging is outside the current release.

The candidate profile linux.flatpak.secret-portal-file.v1 takes the application ID from [Application] name in the fixed /.flatpak-info. It requires a valid [Instance] instance-path and stores ciphertext only at <instance-path>/data/keybay-v2. It ignores FLATPAK_ID, HOME, and XDG_DATA_HOME as identity or storage selectors. Runtime-only metadata, duplicate fields, malformed identity, and unsupported paths fail closed. See the Flatpak metadata reference.

The private directory uses the same descriptor-relative no-follow operations and private permissions as other POSIX profiles. The isolation claim assumes default confinement. A positive xdg-data/keybay-v2 grant, or a grant below that subtree, is rejected because it can remount host data over the store. Broader filesystem or host privileges can weaken isolation; Keybay does not turn them into a portable sandbox guarantee. Flatpak documents these filesystem grants.

Keybay retrieves the sandbox caller’s application secret through XDG Secret Portal v1. The secret is reusable and owned by the portal. The transport accepts 1–4096 bytes; the protector requires 32–4096 bytes, a supported subset of the portal’s variable-length contract. This minimum size does not establish entropy, and HKDF cannot add it. Keybay derives its own 32-byte wrapping root with HKDF-SHA256, the resolved storage domain as salt, and the fixed keybay:v2:linux-flatpak:portal-root:v1 label. It stores no separate Keybay root item and clears operation-owned root buffers after use.

Keybay.open(), authentication changes, and reset may invoke trusted provider UI. Record operations and auth.list() never acquire the portal, including on authentication failure. The initial profile rejects continuation tokens and nonempty persisted provider state. Cancellation, timeout, malformed response, or missing portal fails closed. A detected Flatpak never falls back to ordinary Secret Service, including when that service is reachable.

Portal cancellation reports platformInteractionRequired. Timeout or malformed responses report platformOperationFailed; unavailable providers or unsupported continuation tokens report platformProtectorUnavailable.

Reset deletes the encrypted store and staging, retains the fixed nonsecret coordination lock and its directory, and initializes no replacement store. Unlinking a held lock could let processes lock different inodes. The next successful open generates a fresh store key. The portal exposes no secret deletion API, so reset retains the application secret. Restoring an old complete encrypted store can restore access under the same identity and file domain, with its old credential policy if methods were configured. Rollback resistance and root rotation remain deferred. Changing the Flatpak application ID is a new identity, not migration.

Flatpak qualification

Qualification requires retained Linux evidence of isolation with two installed Flatpak application IDs. Hermetic transport and engine tests cover malformed responses, bounds, token rejection, cancellation, timeout, passphrases, reset, concurrency, and the no-prompt/no-fallback rules.

The three real D-Bus transport tests passed locally on 2026-09-04 with Dart 3.11.0 and 3.12.2 against an isolated D-Bus 1.14.10 daemon on macOS. They exercise Unix descriptor transfer and EOF, early responses, cancellation dispatch, and token rejection using a test portal service. These transport tests cannot prove sandbox caller authentication or per-application isolation. The ordinary Docker Secret Service lane cannot supply that proof either.

The Flatpak lane uses a disposable session bus, the real portal frontend and gnome-keyring Secret backend, and the same AOT harness installed as two minimal Flatpaks with default filtered bus access. It compares in-memory challenge responses from concurrent first requests to prove same-ID continuity and distinct IDs, separately checks private file access, and runs the public SDK lifecycle. It restarts both the portal and keyring and reopens both stores to check that the application secrets persist beyond the provider processes. Qualification also reviews the selected backend’s random-secret generation; length and distinct outputs alone do not establish entropy. No portal secret or derived response is logged or retained. A configured lane is a test plan; only a successful retained run is execution evidence.

Source review of Ubuntu’s GNOME Keyring 46.1 package found independent 64-byte random secrets stored by application ID in the default keyring. This is a review of generation and persistence, not an entropy measurement. Continuity depends on that provider state surviving; deleting or replacing the default keyring can lose access. The lane uses an unlocked backend for this historical run. Later native x64 qualification also exercised prompt cancellation, timeout and overlapping cancellations; see the dated qualification report. Timeout recovery explicitly dismisses any remaining provider dialog; automatic UI dismissal is not claimed.

The complete two-application lane passed locally on 2026-09-05 in Ubuntu 24.04 arm64 under Docker Engine 29.6.1, using Linux 6.12.76-linuxkit, Flatpak 1.14.6, GNOME Keyring 46.1, and XDG Desktop Portal 1.18.4. It verified inner mount/PID namespaces, active seccomp, no-new-privileges, and zero effective capabilities, alongside the identity, file, lifecycle, concurrency, restart, and no-fallback checks above. Native Ubuntu 24.04 x64 CI subsequently passed on 2026-09-06, including the prompted cases. Both receipts apply to their recorded sources and provider configurations, not every Linux desktop; current source applicability is recorded in the qualification report.

Nested Docker needs a private system D-Bus daemon and the outer-container options --security-opt seccomp=unconfined and --security-opt systempaths=unconfined. They permit namespace creation and a private /proc mount; the harness verifies that Flatpak installs its own inner sandbox. The observed run required no privileged mode or added capabilities. See Docker’s seccomp documentation and nested-container mount requirements.

Run bash tool/test_flatpak.sh on Ubuntu 24.04 with the script’s listed prerequisites. It creates and removes a disposable OS account. The integration-flatpak CI job retains a receipt containing versions, application IDs, effective permissions, and result booleans. It emits a passing receipt only after verifying removal of the disposable account, processes, and files.

Snap remains deferred until confinement identity, persistent storage, provider binding, upgrade continuity, and reset behavior qualify together. It never falls back to the ordinary profile.