Shallow snapshot verify ignores object sizes and reports more than it checked #169

Closed
opened 2026-09-22 00:55:14 +02:00 by clawbot · 1 comment
Collaborator

Found by the security review #73 (scope item 3). Severity: low.

What is wrong

snapshot verify without --deep reads the unauthenticated manifest and calls Stat on each listed blob (internal/vaultik/snapshot.go:740-769; line numbers as of next at 6fcd8e1). The size Stat returns is discarded although the manifest carries compressed_size; the deep path already compares it (internal/vaultik/verify.go:615). It never checks that metadata/{remote-key}/db.zst.age exists. A manifest listing no blobs ends in "OK - All blobs verified" (snapshot.go:806), and under --json in status ok.

README.md:74 and :245 describe an existence check accurately. The overclaim is the final status line, the heading "Verify snapshot integrity" (README.md:244) and the CLI short text (internal/cli/snapshot.go:190).

Acceptable

  • Shallow verify fails when a Stat size differs from the manifest's compressed_size, using the same comparison as the deep path, and when db.zst.age is absent.
  • The final line says what was checked, for example: all N blobs listed in the manifest are present with the listed size; contents not checked (use --deep). The README heading and CLI short text say the same.

Definition of done

  1. Tests: a blob object of the wrong size fails shallow verify; a missing db.zst.age fails it.
  2. make fmt over the changed markdown; no existing assertion weakened; make check green.

model: fable-5-1

Found by the security review https://git.eeqj.de/sneak/vaultik/issues/73 (scope item 3). Severity: **low**. ## What is wrong `snapshot verify` without `--deep` reads the unauthenticated manifest and calls `Stat` on each listed blob (`internal/vaultik/snapshot.go:740-769`; line numbers as of `next` at `6fcd8e1`). The size `Stat` returns is discarded although the manifest carries `compressed_size`; the deep path already compares it (`internal/vaultik/verify.go:615`). It never checks that `metadata/{remote-key}/db.zst.age` exists. A manifest listing no blobs ends in "OK - All blobs verified" (`snapshot.go:806`), and under `--json` in status `ok`. `README.md:74` and `:245` describe an existence check accurately. The overclaim is the final status line, the heading "Verify snapshot integrity" (`README.md:244`) and the CLI short text (`internal/cli/snapshot.go:190`). ## Acceptable - Shallow verify fails when a `Stat` size differs from the manifest's `compressed_size`, using the same comparison as the deep path, and when `db.zst.age` is absent. - The final line says what was checked, for example: all N blobs listed in the manifest are present with the listed size; contents not checked (use `--deep`). The README heading and CLI short text say the same. ## Definition of done 1. Tests: a blob object of the wrong size fails shallow verify; a missing `db.zst.age` fails it. 2. `make fmt` over the changed markdown; no existing assertion weakened; `make check` green. model: fable-5-1
Author
Collaborator

Fixed in #193.

Shallow verify now compares each blob's stored size against the manifest's
compressed_size (the same comparison the deep path uses) and requires the
snapshot's encrypted database (db.zst.age) to be present; a wrong-sized
blob or a missing database now fails. The success line reports only what was
checked — presence and size, not contents — and the README and CLI text are
corrected to match. Tests grow one stored blob to force a size mismatch and
delete db.zst.age, each failing shallow verify without the change.

Model: opus-4-8

Fixed in https://git.eeqj.de/sneak/vaultik/pulls/193. Shallow verify now compares each blob's stored size against the manifest's `compressed_size` (the same comparison the deep path uses) and requires the snapshot's encrypted database (`db.zst.age`) to be present; a wrong-sized blob or a missing database now fails. The success line reports only what was checked — presence and size, not contents — and the README and CLI text are corrected to match. Tests grow one stored blob to force a size mismatch and delete `db.zst.age`, each failing shallow verify without the change. Model: opus-4-8
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/vaultik#169