Skip to content

Commit d19dc5b

Browse files
Fix crash with missing checkpoint (#260)
It was assumed that if an inclusion proof is present, then a checkpoint would be present too. Some bundles exist where the checkpoint was not present, particularly for v0.1. This is a bug, so we should err out, but we shouldn't crash if the checkpoint is missing. Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
1 parent 004c425 commit d19dc5b

File tree

2 files changed

+153
-8
lines changed

2 files changed

+153
-8
lines changed

pkg/bundle/bundle_test.go

Lines changed: 146 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import (
2525

2626
protobundle "github.com/sigstore/protobuf-specs/gen/pb-go/bundle/v1"
2727
protocommon "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1"
28-
v1 "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1"
2928
rekorv1 "github.com/sigstore/protobuf-specs/gen/pb-go/rekor/v1"
3029
_ "github.com/sigstore/rekor/pkg/types/hashedrekord"
3130
"github.com/stretchr/testify/require"
@@ -280,7 +279,79 @@ func Test_validate(t *testing.T) {
280279
},
281280
},
282281
Content: &protobundle.VerificationMaterial_PublicKey{
283-
PublicKey: &v1.PublicKeyIdentifier{},
282+
PublicKey: &protocommon.PublicKeyIdentifier{},
283+
},
284+
},
285+
Content: &protobundle.Bundle_MessageSignature{},
286+
},
287+
},
288+
},
289+
{
290+
name: "v0.1 with inclusion promise & proof without checkpoint",
291+
pb: Bundle{
292+
Bundle: &protobundle.Bundle{
293+
MediaType: "application/vnd.dev.sigstore.bundle+json;version=0.1",
294+
VerificationMaterial: &protobundle.VerificationMaterial{
295+
TlogEntries: []*rekorv1.TransparencyLogEntry{
296+
{
297+
LogIndex: 42,
298+
LogId: &protocommon.LogId{
299+
KeyId: []byte("deadbeef"),
300+
},
301+
KindVersion: &rekorv1.KindVersion{
302+
Kind: "hashedrekord",
303+
Version: "0.0.1",
304+
},
305+
IntegratedTime: 1,
306+
CanonicalizedBody: canonicalTlogBody,
307+
InclusionProof: &rekorv1.InclusionProof{
308+
LogIndex: 42,
309+
RootHash: []byte("b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c"),
310+
},
311+
InclusionPromise: &rekorv1.InclusionPromise{
312+
SignedEntryTimestamp: []byte("1"),
313+
},
314+
},
315+
},
316+
Content: &protobundle.VerificationMaterial_PublicKey{
317+
PublicKey: &protocommon.PublicKeyIdentifier{},
318+
},
319+
},
320+
Content: &protobundle.Bundle_MessageSignature{},
321+
},
322+
},
323+
wantErr: true,
324+
},
325+
{
326+
name: "v0.1 with inclusion proof & promise",
327+
pb: Bundle{
328+
Bundle: &protobundle.Bundle{
329+
MediaType: "application/vnd.dev.sigstore.bundle+json;version=0.1",
330+
VerificationMaterial: &protobundle.VerificationMaterial{
331+
TlogEntries: []*rekorv1.TransparencyLogEntry{
332+
{
333+
LogIndex: 42,
334+
LogId: &protocommon.LogId{
335+
KeyId: []byte("deadbeef"),
336+
},
337+
KindVersion: &rekorv1.KindVersion{
338+
Kind: "hashedrekord",
339+
Version: "0.0.1",
340+
},
341+
IntegratedTime: 1,
342+
CanonicalizedBody: canonicalTlogBody,
343+
InclusionProof: &rekorv1.InclusionProof{
344+
LogIndex: 42,
345+
RootHash: []byte("b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c"),
346+
Checkpoint: &rekorv1.Checkpoint{Envelope: "checkpoint"},
347+
},
348+
InclusionPromise: &rekorv1.InclusionPromise{
349+
SignedEntryTimestamp: []byte("1"),
350+
},
351+
},
352+
},
353+
Content: &protobundle.VerificationMaterial_PublicKey{
354+
PublicKey: &protocommon.PublicKeyIdentifier{},
284355
},
285356
},
286357
Content: &protobundle.Bundle_MessageSignature{},
@@ -308,7 +379,7 @@ func Test_validate(t *testing.T) {
308379
},
309380
},
310381
Content: &protobundle.VerificationMaterial_PublicKey{
311-
PublicKey: &v1.PublicKeyIdentifier{},
382+
PublicKey: &protocommon.PublicKeyIdentifier{},
312383
},
313384
},
314385
Content: &protobundle.Bundle_MessageSignature{},
@@ -317,7 +388,40 @@ func Test_validate(t *testing.T) {
317388
wantErr: true,
318389
},
319390
{
320-
name: "v0.2 with inclusion proof",
391+
name: "v0.2 with inclusion proof without checkpoint",
392+
pb: Bundle{
393+
Bundle: &protobundle.Bundle{
394+
MediaType: "application/vnd.dev.sigstore.bundle+json;version=0.2",
395+
VerificationMaterial: &protobundle.VerificationMaterial{
396+
TlogEntries: []*rekorv1.TransparencyLogEntry{
397+
{
398+
LogIndex: 42,
399+
LogId: &protocommon.LogId{
400+
KeyId: []byte("deadbeef"),
401+
},
402+
KindVersion: &rekorv1.KindVersion{
403+
Kind: "hashedrekord",
404+
Version: "0.0.1",
405+
},
406+
IntegratedTime: 1,
407+
CanonicalizedBody: canonicalTlogBody,
408+
InclusionProof: &rekorv1.InclusionProof{
409+
LogIndex: 42,
410+
RootHash: []byte("b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c"),
411+
},
412+
},
413+
},
414+
Content: &protobundle.VerificationMaterial_PublicKey{
415+
PublicKey: &protocommon.PublicKeyIdentifier{},
416+
},
417+
},
418+
Content: &protobundle.Bundle_MessageSignature{},
419+
},
420+
},
421+
wantErr: true,
422+
},
423+
{
424+
name: "v0.2 with inclusion proof with empty checkpoint",
321425
pb: Bundle{
322426
Bundle: &protobundle.Bundle{
323427
MediaType: "application/vnd.dev.sigstore.bundle+json;version=0.2",
@@ -342,7 +446,41 @@ func Test_validate(t *testing.T) {
342446
},
343447
},
344448
Content: &protobundle.VerificationMaterial_PublicKey{
345-
PublicKey: &v1.PublicKeyIdentifier{},
449+
PublicKey: &protocommon.PublicKeyIdentifier{},
450+
},
451+
},
452+
Content: &protobundle.Bundle_MessageSignature{},
453+
},
454+
},
455+
wantErr: true,
456+
},
457+
{
458+
name: "v0.2 with inclusion proof",
459+
pb: Bundle{
460+
Bundle: &protobundle.Bundle{
461+
MediaType: "application/vnd.dev.sigstore.bundle+json;version=0.2",
462+
VerificationMaterial: &protobundle.VerificationMaterial{
463+
TlogEntries: []*rekorv1.TransparencyLogEntry{
464+
{
465+
LogIndex: 42,
466+
LogId: &protocommon.LogId{
467+
KeyId: []byte("deadbeef"),
468+
},
469+
KindVersion: &rekorv1.KindVersion{
470+
Kind: "hashedrekord",
471+
Version: "0.0.1",
472+
},
473+
IntegratedTime: 1,
474+
CanonicalizedBody: canonicalTlogBody,
475+
InclusionProof: &rekorv1.InclusionProof{
476+
LogIndex: 42,
477+
RootHash: []byte("b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c"),
478+
Checkpoint: &rekorv1.Checkpoint{Envelope: "checkpoint"},
479+
},
480+
},
481+
},
482+
Content: &protobundle.VerificationMaterial_PublicKey{
483+
PublicKey: &protocommon.PublicKeyIdentifier{},
346484
},
347485
},
348486
Content: &protobundle.Bundle_MessageSignature{},
@@ -370,7 +508,7 @@ func Test_validate(t *testing.T) {
370508
InclusionProof: &rekorv1.InclusionProof{
371509
LogIndex: 42,
372510
RootHash: []byte("b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c"),
373-
Checkpoint: &rekorv1.Checkpoint{},
511+
Checkpoint: &rekorv1.Checkpoint{Envelope: "checkpoint"},
374512
},
375513
},
376514
},
@@ -404,7 +542,7 @@ func Test_validate(t *testing.T) {
404542
InclusionProof: &rekorv1.InclusionProof{
405543
LogIndex: 42,
406544
RootHash: []byte("b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c"),
407-
Checkpoint: &rekorv1.Checkpoint{},
545+
Checkpoint: &rekorv1.Checkpoint{Envelope: "checkpoint"},
408546
},
409547
},
410548
},
@@ -818,7 +956,7 @@ func Test_BundleValidation(t *testing.T) {
818956
Content: &protobundle.Bundle_DsseEnvelope{},
819957
VerificationMaterial: &protobundle.VerificationMaterial{
820958
Content: &protobundle.VerificationMaterial_PublicKey{
821-
PublicKey: &v1.PublicKeyIdentifier{},
959+
PublicKey: &protocommon.PublicKeyIdentifier{},
822960
},
823961
TimestampVerificationData: &protobundle.TimestampVerificationData{},
824962
},

pkg/tlog/entry.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,13 @@ func ParseEntry(protoEntry *v1.TransparencyLogEntry) (entry *Entry, err error) {
124124

125125
rootHash := hex.EncodeToString(protoEntry.InclusionProof.RootHash)
126126

127+
if protoEntry.InclusionProof.Checkpoint == nil {
128+
return nil, fmt.Errorf("inclusion proof missing required checkpoint")
129+
}
130+
if protoEntry.InclusionProof.Checkpoint.Envelope == "" {
131+
return nil, fmt.Errorf("inclusion proof checkpoint empty")
132+
}
133+
127134
inclusionProof = &models.InclusionProof{
128135
LogIndex: swag.Int64(protoEntry.InclusionProof.LogIndex),
129136
RootHash: &rootHash,

0 commit comments

Comments
 (0)