Skip to content

Commit 17b4808

Browse files
authored
Do not allow empty hashes for the Target role (#721)
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
1 parent d361e2e commit 17b4808

File tree

3 files changed

+35
-3
lines changed

3 files changed

+35
-3
lines changed

metadata/marshal.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,10 @@ func (signed *TargetFiles) UnmarshalJSON(data []byte) error {
230230
if err := json.Unmarshal(data, &s); err != nil {
231231
return err
232232
}
233+
// Per TUF spec, hashes are mandatory for target files
234+
if len(s.Hashes) == 0 {
235+
return fmt.Errorf("hashes must not be empty for target files")
236+
}
233237
*signed = TargetFiles(s)
234238

235239
var dict map[string]any

metadata/metadata.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,10 @@ func (f *MetaFiles) VerifyLengthHashes(data []byte) error {
458458
// VerifyLengthHashes checks whether the TargetFiles data matches its corresponding
459459
// length and hashes
460460
func (f *TargetFiles) VerifyLengthHashes(data []byte) error {
461+
// Per TUF spec, hashes are mandatory for target files
462+
if len(f.Hashes) == 0 {
463+
return &ErrLengthOrHashMismatch{Msg: "hashes must not be empty for target files"}
464+
}
461465
err := verifyHashes(data, f.Hashes)
462466
if err != nil {
463467
return err

metadata/metadata_test.go

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -666,13 +666,13 @@ func TestVerifyLengthHashesTargetFiles(t *testing.T) {
666666
targetFiles := TargetFile()
667667
targetFiles.Hashes = map[string]HexBytes{}
668668

669+
// Per TUF spec, empty hashes must be rejected
669670
data := []byte{}
670671
err := targetFiles.VerifyLengthHashes(data)
671-
assert.NoError(t, err)
672+
assert.Error(t, err)
673+
assert.Contains(t, err.Error(), "hashes must not be empty")
672674

673675
data = []byte("some data")
674-
err = targetFiles.VerifyLengthHashes(data)
675-
assert.Error(t, err, "length/hash verification error: length verification failed - expected 0, got 9")
676676

677677
h32 := sha256.Sum256(data)
678678
h := h32[:]
@@ -712,3 +712,27 @@ func TestVerifyLengthHashesMetaFiles(t *testing.T) {
712712
err = metaFile.VerifyLengthHashes(incorrectData)
713713
assert.Error(t, err, "length/hash verification error: length verification failed - expected 0, got 9")
714714
}
715+
716+
func TestTargetFilesEmptyHashesRejected(t *testing.T) {
717+
// Per TUF spec, hashes are mandatory for target files.
718+
// Targets metadata with empty hashes should be rejected at parse time.
719+
targetsJSON := []byte(`{
720+
"signatures": [],
721+
"signed": {
722+
"_type": "targets",
723+
"expires": "2030-08-15T14:30:45Z",
724+
"spec_version": "1.0.31",
725+
"targets": {
726+
"test.txt": {
727+
"hashes": {},
728+
"length": 100
729+
}
730+
},
731+
"version": 1
732+
}
733+
}`)
734+
735+
_, err := Targets().FromBytes(targetsJSON)
736+
assert.Error(t, err)
737+
assert.Contains(t, err.Error(), "hashes must not be empty")
738+
}

0 commit comments

Comments
 (0)