secret mv --force onto the same secret deletes it #73

Open
opened 2026-10-03 17:37:18 +02:00 by clawbot · 2 comments
Collaborator

Found in the review of #65 (#65 (comment)). Present on next.

Problem

moveSecretWithinVault (internal/cli/secrets.go) removes the destination with RemoveAll before renaming the source onto it. When the destination is the source, that deletes the secret and every version of it:

  • secret mv --force x x
  • secret mv --force work:x work:
  • secret mv --force work:x "": the empty destination defaults to the source name, so an empty shell variable is enough.

On the in-memory filesystem the command even reports success.

Also, a qualified move within one vault that then fails (for example secret mv work:nosuch work:y) still leaves work as the current vault.

Definition of done

  • A move whose destination resolves to the source (same vault, same name, with or without --force) is rejected with a clear error before anything under the state directory is changed.
  • A move within one vault never changes the current vault, whether it succeeds or fails.
  • Tests record every file and directory under the state directory (with contents) before each case and require an unchanged record after: mv --force x x, mv --force work:x work:, mv --force work:x "", and mv work:nosuch work:y with another vault current.
  • TODO.md updated in the same commit.

Sequencing

After #65 lands (same function, and its state-recording test helper is reused).

Model: opus-5-5

Found in the review of https://git.eeqj.de/sneak/secret/pulls/65 (https://git.eeqj.de/sneak/secret/pulls/65#issuecomment-117517). Present on `next`. ## Problem `moveSecretWithinVault` (`internal/cli/secrets.go`) removes the destination with `RemoveAll` before renaming the source onto it. When the destination is the source, that deletes the secret and every version of it: - `secret mv --force x x` - `secret mv --force work:x work:` - `secret mv --force work:x ""`: the empty destination defaults to the source name, so an empty shell variable is enough. On the in-memory filesystem the command even reports success. Also, a qualified move within one vault that then fails (for example `secret mv work:nosuch work:y`) still leaves `work` as the current vault. ## Definition of done - A move whose destination resolves to the source (same vault, same name, with or without `--force`) is rejected with a clear error before anything under the state directory is changed. - A move within one vault never changes the current vault, whether it succeeds or fails. - Tests record every file and directory under the state directory (with contents) before each case and require an unchanged record after: `mv --force x x`, `mv --force work:x work:`, `mv --force work:x ""`, and `mv work:nosuch work:y` with another vault current. - `TODO.md` updated in the same commit. ## Sequencing After https://git.eeqj.de/sneak/secret/pulls/65 lands (same function, and its state-recording test helper is reused). Model: opus-5-5
clawbot added the critical label 2026-10-03 17:37:18 +02:00
Author
Collaborator

Labelled critical: secret mv --force x x, or secret mv --force work:x "" with an empty shell variable, deletes the secret and all its versions.

Model: opus-5-5

Labelled critical: `secret mv --force x x`, or `secret mv --force work:x ""` with an empty shell variable, deletes the secret and all its versions. Model: opus-5-5
Author
Collaborator

#76: a move whose destination is the source is now rejected before anything changes, and a move within a named vault no longer makes that vault the current one.

Model: opus-5-5

https://git.eeqj.de/sneak/secret/pulls/76: a move whose destination is the source is now rejected before anything changes, and a move within a named vault no longer makes that vault the current one. 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#73