A retention duration of 293 years or more deletes every snapshot #289

Closed
opened 2026-10-13 00:29:18 +02:00 by clawbot · 1 comment
Collaborator

Found by the defect hunt in #288 (part 4).

What is wrong: parseDuration (internal/vaultik/helpers.go) computes time.Duration(n) * year (and the same for w, mo, d) with no overflow check. From 293y up the product wraps to a negative value, so selectSnapshotsToPurge (internal/vaultik/snapshot.go) puts the cutoff in the future and selects every snapshot. A user who writes --prune --keep-newer-than 1000y to keep everything loses every snapshot of that name, including the one just made, and PruneBlobs then deletes their blobs. The command exits 0.

How it was shown: after two backups, snapshot purge --older-than 1000y listed all four snapshots, including one a second old. 292y lists none; 293y, 15300w and 3600mo list all. snapshot create --cron --prune --keep-newer-than 1000y home exited 0 and left no home snapshot and none of its blobs.

Definition of done

  • A duration too large to represent (in any unit, and summed over several parts such as 200y200y) is rejected as invalid, with a non-zero exit and nothing deleted, for --keep-newer-than and --older-than alike.
  • No duration ever selects a snapshot newer than it.
  • A test covers the overflow for each unit and for a sum of parts.

Model: opus-5-5

Found by the defect hunt in https://git.eeqj.de/sneak/vaultik/issues/288 (part 4). **What is wrong:** `parseDuration` (`internal/vaultik/helpers.go`) computes `time.Duration(n) * year` (and the same for `w`, `mo`, `d`) with no overflow check. From `293y` up the product wraps to a negative value, so `selectSnapshotsToPurge` (`internal/vaultik/snapshot.go`) puts the cutoff in the future and selects every snapshot. A user who writes `--prune --keep-newer-than 1000y` to keep everything loses every snapshot of that name, including the one just made, and `PruneBlobs` then deletes their blobs. The command exits 0. **How it was shown:** after two backups, `snapshot purge --older-than 1000y` listed all four snapshots, including one a second old. `292y` lists none; `293y`, `15300w` and `3600mo` list all. `snapshot create --cron --prune --keep-newer-than 1000y home` exited 0 and left no `home` snapshot and none of its blobs. **Definition of done** - A duration too large to represent (in any unit, and summed over several parts such as `200y200y`) is rejected as invalid, with a non-zero exit and nothing deleted, for `--keep-newer-than` and `--older-than` alike. - No duration ever selects a snapshot newer than it. - A test covers the overflow for each unit and for a sum of parts. Model: opus-5-5
clawbot self-assigned this 2026-10-13 00:29:18 +02:00
clawbot added the critical label 2026-10-13 00:30:18 +02:00
Author
Collaborator

Fixed in #328: a duration whose total no longer fits in a time.Duration (about 292 years) is now rejected as invalid, so a purge with it stops before anything is deleted.

Model: opus-5-5

Fixed in https://git.eeqj.de/sneak/vaultik/pulls/328: a duration whose total no longer fits in a `time.Duration` (about 292 years) is now rejected as invalid, so a purge with it stops before anything is deleted. 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/vaultik#289