Replacing an unlocker is not atomic: a crash part-way leaves it unable to open the vault #71

Closed
opened 2026-10-03 15:02:43 +02:00 by clawbot · 1 comment
Collaborator

An unlocker is rewritten in place, one file after another, when it is added under the directory name of an existing one:

  • passphrase: a vault has at most one, in unlockers.d/passphrase, so secret unlocker add passphrase on a vault that has one rewrites it;
  • PGP, keychain and Secure Enclave: the directory is named after the host and the day (a PGP one, for example, myhost-pgp-2026-10-03), so adding a second unlocker of the same type on the same host on the same day rewrites the first.

Each file is replaced in one rename (#69), but the files are not replaced together: a crash between two of those writes leaves an unlocker whose files do not belong together, for example a private key that cannot decrypt the longterm.age beside it. When that unlocker is the current one, the vault then opens only with the mnemonic.

Replacing an unlocker atomically needs the new one written to a directory of its own, current-unlocker switched to it, and only then the old directory removed. That changes how unlocker directories are named, so it was left out of #69.

Model: opus-5-5

An unlocker is rewritten in place, one file after another, when it is added under the directory name of an existing one: - passphrase: a vault has at most one, in `unlockers.d/passphrase`, so `secret unlocker add passphrase` on a vault that has one rewrites it; - PGP, keychain and Secure Enclave: the directory is named after the host and the day (a PGP one, for example, `myhost-pgp-2026-10-03`), so adding a second unlocker of the same type on the same host on the same day rewrites the first. Each file is replaced in one rename (https://git.eeqj.de/sneak/secret/pulls/69), but the files are not replaced together: a crash between two of those writes leaves an unlocker whose files do not belong together, for example a private key that cannot decrypt the `longterm.age` beside it. When that unlocker is the current one, the vault then opens only with the mnemonic. Replacing an unlocker atomically needs the new one written to a directory of its own, `current-unlocker` switched to it, and only then the old directory removed. That changes how unlocker directories are named, so it was left out of https://git.eeqj.de/sneak/secret/pulls/69. Model: opus-5-5
clawbot changed title from Replacing a passphrase unlocker is not atomic: a crash part-way leaves it unable to open the vault to Replacing an unlocker is not atomic: a crash part-way leaves it unable to open the vault 2026-10-03 16:43:00 +02:00
Author
Collaborator

Built in #99: every new unlocker gets a directory of its own, and adding a passphrase unlocker points current-unlocker at the new one before removing the old. A PGP, keychain or Secure Enclave unlocker added on the same day as another is now kept beside it. Follow-up found on the way: #98.

Model: opus-5-5

Built in https://git.eeqj.de/sneak/secret/pulls/99: every new unlocker gets a directory of its own, and adding a passphrase unlocker points `current-unlocker` at the new one before removing the old. A PGP, keychain or Secure Enclave unlocker added on the same day as another is now kept beside it. Follow-up found on the way: https://git.eeqj.de/sneak/secret/issues/98. Model: opus-5-5
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/secret#71