Validate blob hashes, offsets and lengths from the destination (closes #155)
A blob hash read back from the downloaded snapshot database or the store listing was trusted unchecked. A hostile remote could set a hash such as "aa/../../etc" and have a decrypted blob written outside the cache directory, or feed a short or negative value that panicked a command. blobDiskCache.path now refuses any key with a path separator, and ReadAt rejects a negative offset or length, bounding so a sum cannot overflow past the check. A new isBlobHash helper gates FetchBlob, shallow and deep verify, and restore: buildBlobIndexes rejects every hash from the snapshot database before any fetch. The blobs/ and metadata/ listings skip a non-conforming name, and short-hash prefixes in log and error text go through a panic-safe shortHash helper. Model: opus-4-8
This commit was merged in pull request #195.
This commit is contained in:
1 parent
d88ed64489
commit
82c51a5337
10 files changed
+549
-53
No files matched your search
@@ -55,6 +55,35 @@ func buildHashTestBlob(
|
||||
return encBuf.Bytes(), correctHash
|
||||
}
|
||||
|
||||
// TestFetchBlobRejectsMalformedHash verifies FetchBlob refuses a blob hash
|
||||
// that is not 64 lowercase hex characters before it builds a storage path
|
||||
// or issues any request. The hash reaches FetchBlob from the snapshot
|
||||
// database, which is not trusted, so a value such as one containing "/.."
|
||||
// must never reach the store.
|
||||
func TestFetchBlobRejectsMalformedHash(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
mockStorage := NewMockStorer()
|
||||
tv := vaultik.NewForTesting(mockStorage)
|
||||
ctx := context.Background()
|
||||
|
||||
for _, bad := range []string{
|
||||
"aa/../../../home/u/.profile",
|
||||
"abc",
|
||||
strings.Repeat("A", 64), // uppercase hex is not accepted
|
||||
strings.Repeat("g", 64), // not hex
|
||||
} {
|
||||
_, _, err := tv.FetchBlob(ctx, bad, 0)
|
||||
if err == nil {
|
||||
t.Fatalf("expected error for malformed hash %q, got nil", bad)
|
||||
}
|
||||
}
|
||||
|
||||
if calls := mockStorage.GetCalls(); len(calls) != 0 {
|
||||
t.Fatalf("storage was accessed for a malformed hash: %v", calls)
|
||||
}
|
||||
}
|
||||
|
||||
// TestFetchAndDecryptBlobVerifiesHash verifies that FetchAndDecryptBlob checks
|
||||
// the double-SHA-256 hash of the decrypted plaintext against the expected blob hash.
|
||||
func TestFetchAndDecryptBlobVerifiesHash(t *testing.T) {
|
||||
|
||||
Reference in new issue
Block a user