fix(keychain): unlock the item on relock, not just the collection - #630
Merged
Conversation
…st the collection Saving or updating a credential could fail permanently with `org.freedesktop.Secret.Error.IsLocked` on Linux backends that lock an item independently of its enclosing collection. `Service.Unlock` accepts both collection and item object paths, but every retry in `withRelockRetry` (and its callers in Delete/Get/Save/loadSecret) only ever unlocked the collection, so an independently locked item stayed locked forever and the retried SetItemSecret/DeleteItem/GetSecret call kept failing with the same error. Thread the relevant item's object path into withRelockRetry wherever one is already known (Delete, Get, Save's SetItemSecret and duplicate DeleteItem, loadSecret's GetSecret) so the retry unlocks the item alongside its collection. Signed-off-by: Remy Suen <remy.suen@docker.com> Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
NewService added its signal match rule as a bare key=value pair with the interface name as the key. That is not a valid match rule, the bus rejects it, and the error was discarded — so the connection never subscribed to org.freedesktop.Secret.Prompt.Completed and PromptAndWait timed out on every real (non-null) prompt, even after the user confirmed it. The passwordless gnome-keyring test environment only ever produces null prompts, which is why this never surfaced there. Use interface and member match options instead, and fail NewService if the subscription cannot be established. Verified against KeePassXC's secret service with per-item access confirmation enabled: unlocking an independently locked item now completes once the access prompt is allowed, where it previously timed out after 30 seconds. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
Trim the itemPaths documentation to its contract and drop the test comments and assertion prose that restated it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
joe0BAB
approved these changes
Aug 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes docker/sbx-releases#340:
saving credentials: failed to set item secret: org.freedesktop.Secret.Error.IsLockedon Linux Secret Service backends that lock an item independently of its collection — e.g. KeePassXC, whose per-item access confirmation (on by default) reports every item locked until the client is allowed, even while the collection is unlocked.Two bugs, both required for recovery:
Service.Unlocktake item paths, butwithRelockRetrynever passed one, so an independently locked item stayed locked and the retriedSetItemSecret/DeleteItem/GetSecretfailed forever.Delete,Get,Save, andloadSecretnow pass the item's path so it is unlocked alongside the collection (CreateItemunchanged — no item exists yet).NewServiceregistered the invalid match ruleorg.freedesktop.Secret.Prompt='Completed'(a bare key=value pair) and discarded the bus's rejection, soPromptAndWaittimed out on every real prompt even after the user confirmed it — and unlocking an item on KeePassXC raises exactly such a prompt, so fix 1 alone still failed. Now subscribes viaWithMatchInterface+WithMatchMemberand failsNewServiceif the subscription is rejected. Never surfaced on gnome-keyring: passwordless keyrings answerUnlockwith the null prompt.Validation
Unlockincludes the item path (fail without fix 1).DOCKER_TARGET=ubuntu-24-gnome-keyring make keychain-linux-ci-unit-testspasses — no regression (gnome-keyring locks at collection granularity only).ConfirmAccessItemon): reproduced the reported error byte-for-byte;Unlock([collection])alone never recovers; with both fixes,Unlock([collection, item])raises the access prompt and the retried write succeeds once allowed. With only fix 1 it still failed — 30s timeout waiting for aPrompt.Completedsignal that was never subscribed.🤖 Generated with Claude Code