A blob's hash — its remote filename — is the double SHA256 of the plaintext (internal/blobgen/writer.go, Sum256). Deep verification's final integrity step (internal/vaultik/verify.go, verifyBlobFinalIntegrity) instead hashes the encrypted downloaded bytes with a single SHA256 and compares that to the blob hash. The two can never be equal, so verify --deep fails on every valid blob with blob hash mismatch.
The per-chunk hash checks in the same path are correct; only the final blob-hash comparison is wrong.
Effect: deep verification is unusable — it reports healthy backups as corrupt. The blob-existence stage that runs earlier is unaffected, so a genuinely missing blob is still caught.
Reproduction: internal/vaultik/fault_injection_test.go, TestFaultInjection_DeepVerifyAcceptsHealthySnapshot (skipped, points to this issue).
Model: opus-4-8
Found while adding fault-injection tests for https://git.eeqj.de/sneak/vaultik/issues/72.
A blob's hash — its remote filename — is the double SHA256 of the plaintext (`internal/blobgen/writer.go`, `Sum256`). Deep verification's final integrity step (`internal/vaultik/verify.go`, `verifyBlobFinalIntegrity`) instead hashes the encrypted downloaded bytes with a single SHA256 and compares that to the blob hash. The two can never be equal, so `verify --deep` fails on every valid blob with `blob hash mismatch`.
The per-chunk hash checks in the same path are correct; only the final blob-hash comparison is wrong.
Effect: deep verification is unusable — it reports healthy backups as corrupt. The blob-existence stage that runs earlier is unaffected, so a genuinely missing blob is still caught.
Reproduction: `internal/vaultik/fault_injection_test.go`, `TestFaultInjection_DeepVerifyAcceptsHealthySnapshot` (skipped, points to this issue).
Model: opus-4-8
clawbot
added this to the 1.0.0 milestone 2026-09-21 09:47:34 +02:00
Fixed in #138 (base next). Deep verification now hashes the decompressed plaintext and compares its double SHA256 to the blob name, instead of single-hashing the encrypted bytes. Added a test that backs up a real snapshot, deep-verifies it (fails before the fix), then flips a byte in one stored blob and confirms deep verification then fails.
Model: opus-4-8
Fixed in https://git.eeqj.de/sneak/vaultik/pulls/138 (base `next`). Deep verification now hashes the decompressed plaintext and compares its double SHA256 to the blob name, instead of single-hashing the encrypted bytes. Added a test that backs up a real snapshot, deep-verifies it (fails before the fix), then flips a byte in one stored blob and confirms deep verification then fails.
Model: opus-4-8
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Found while adding fault-injection tests for #72.
A blob's hash — its remote filename — is the double SHA256 of the plaintext (
internal/blobgen/writer.go,Sum256). Deep verification's final integrity step (internal/vaultik/verify.go,verifyBlobFinalIntegrity) instead hashes the encrypted downloaded bytes with a single SHA256 and compares that to the blob hash. The two can never be equal, soverify --deepfails on every valid blob withblob hash mismatch.The per-chunk hash checks in the same path are correct; only the final blob-hash comparison is wrong.
Effect: deep verification is unusable — it reports healthy backups as corrupt. The blob-existence stage that runs earlier is unaffected, so a genuinely missing blob is still caught.
Reproduction:
internal/vaultik/fault_injection_test.go,TestFaultInjection_DeepVerifyAcceptsHealthySnapshot(skipped, points to this issue).Model: opus-4-8
Fixed in #138 (base
next). Deep verification now hashes the decompressed plaintext and compares its double SHA256 to the blob name, instead of single-hashing the encrypted bytes. Added a test that backs up a real snapshot, deep-verifies it (fails before the fix), then flips a byte in one stored blob and confirms deep verification then fails.Model: opus-4-8