1 Commits
Author SHA1 Message Date
sneak b33bb52240 A secret mv between vaults unlocks both vaults before taking the lock (closes #189)
check / check (push) Canceled after 0s
A move between two vaults unlocked them while holding the state directory
lock, and unlocking can ask for a passphrase, so every other changing
command waited at that prompt. moveSecretCrossVault now checks the move,
unlocks both vaults, and only then takes the lock. Under the lock,
copySecretAndRemoveSource checks again that the source and the destination
vault still exist, then copies. A move within a vault takes the lock in
moveSecretWithinVault, so MoveSecret takes none itself.

The two tests of a source that cannot be removed now call
copySecretAndRemoveSource, since the lock refuses their wrapped
filesystems.

Model: opus-5-5
2026-10-15 05:52:04 +00:00
+4 -7
View File
@@ -1025,19 +1025,16 @@ func (cli *Instance) sameDirectory(dir, other string) (bool, error) {
// moveSecretCrossVault handles moving between two different vaults. Its // moveSecretCrossVault handles moving between two different vaults. Its
// caller, MoveSecret, has already checked both secret names and that both // caller, MoveSecret, has already checked both secret names and that both
// vaults exist. The copy needs the source vault's long-term key; the // vaults exist. Copying needs the long-term keys of both vaults, and getting
// destination vault is unlocked only to check that it can be. Either can ask // one can ask for a passphrase, so it gets them before it takes the state
// for a passphrase, so both happen before it takes the state directory lock, // directory lock, and no other command waits while the user answers.
// and no other command waits while the user answers.
func (cli *Instance) moveSecretCrossVault( func (cli *Instance) moveSecretCrossVault(
cmd *cobra.Command, cmd *cobra.Command,
srcVault *vault.Vault, srcSecretName string, srcVault *vault.Vault, srcSecretName string,
destVault *vault.Vault, destSecretName string, destVault *vault.Vault, destSecretName string,
force bool, force bool,
) error { ) error {
// Before unlocking, check that the source secret and the destination // Refuse a move that cannot be made before asking for anything
// vault exist, and that the destination is not the source under another
// name
_, err := cli.checkCrossVaultMove( _, err := cli.checkCrossVaultMove(
srcVault, srcSecretName, destVault, destSecretName) srcVault, srcSecretName, destVault, destSecretName)
if err != nil { if err != nil {