Skip to content

Commit

Permalink
fix verifyIntotoTypes()
Browse files Browse the repository at this point in the history
Signed-off-by: Ramon Petgrave <ramon.petgrave64@gmail.com>
  • Loading branch information
ramonpetgrave64 committed May 28, 2024
1 parent fa4b631 commit 99fc0bc
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 43 deletions.
49 changes: 34 additions & 15 deletions verifiers/internal/gha/npm.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ const (
publishAttestationV01 = "https://github.com/npm/attestation/tree/main/specs/publish/"
)

var intotoStatements = map[string]bool{
intoto.StatementInTotoV01: true,
"https://in-toto.io/Statement/v1": true,
}
var provenancePredicates = map[string]bool{
common.ProvenanceV02Type: true,
common.ProvenanceV1Type: true,
}
var publishPredicates = map[string]bool{
publishAttestationV01: true,
}
var errrorInvalidAttestations = errors.New("invalid npm attestations")
var attestationKeyAtomicValue atomic.Value

Expand Down Expand Up @@ -174,18 +185,16 @@ func (n *Npm) verifyPublishAttestationSignature() error {
}

func (n *Npm) verifyIntotoHeaders() error {
if err := verifyIntotoTypes(n.verifiedProvenanceAtt,
common.ProvenanceV02Type, intoto.PayloadType, false); err != nil {
if err := verifyIntotoTypes(n.verifiedProvenanceAtt, provenancePredicates, intoto.PayloadType, false); err != nil {
return err
}
if err := verifyIntotoTypes(n.verifiedPublishAtt,
publishAttestationV01, intoto.PayloadType, true); err != nil {
if err := verifyIntotoTypes(n.verifiedPublishAtt, publishPredicates, intoto.PayloadType, true); err != nil {
return err
}
return nil
}

func verifyIntotoTypes(att *SignedAttestation, predicateType, payloadType string, prefix bool) error {
func verifyIntotoTypes(att *SignedAttestation, pridicateTypes map[string]bool, payloadType string, prefix bool) error {
env := att.Envelope
pyld, err := base64.StdEncoding.DecodeString(env.Payload)
if err != nil {
Expand All @@ -204,20 +213,30 @@ func verifyIntotoTypes(att *SignedAttestation, predicateType, payloadType string
}

// Statement verification.
if statement.Type != intoto.StatementInTotoV01 {
return fmt.Errorf("%w: expected statement type '%v', got '%s'",
serrors.ErrorInvalidDssePayload, intoto.StatementInTotoV01, statement.Type)
if _, exists := intotoStatements[statement.Type]; !exists {
return fmt.Errorf("%w: expected statement header type one of '%v', got '%s'",
serrors.ErrorInvalidDssePayload, intotoStatements, statement.Type)
}

if !prefix && statement.PredicateType != predicateType {
return fmt.Errorf("%w: expected predicate type '%v', got '%s'",
serrors.ErrorInvalidDssePayload, predicateType, statement.PredicateType)
}
if prefix && !strings.HasPrefix(statement.PredicateType, predicateType) {
return fmt.Errorf("%w: expected predicate type '%v', got '%s'",
serrors.ErrorInvalidDssePayload, predicateType, statement.PredicateType)
if !prefix {
if _, exists := pridicateTypes[statement.PredicateType]; !exists {
return fmt.Errorf("%w: expected predicate type one of '%v', got '%s'", serrors.ErrorInvalidDssePayload, pridicateTypes, statement.PredicateType)
}
}

if prefix {
hasPrefix := false
for k := range pridicateTypes {
if strings.HasPrefix(statement.PredicateType, k) {
hasPrefix = true
break
}
}
if !hasPrefix {
return fmt.Errorf("%w: expected predicate type with prefix one of '%v', got '%s'",
serrors.ErrorInvalidDssePayload, pridicateTypes, statement.PredicateType)
}
}
return nil
}

Expand Down
65 changes: 37 additions & 28 deletions verifiers/internal/gha/npm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ import (
"github.com/slsa-framework/slsa-verifier/v2/verifiers/utils"
)

var mismatchProvenancePredicates = map[string]bool{
common.ProvenanceV02Type + "a": true,
common.ProvenanceV1Type + "a": true,
}
var mismatchPublishPredicates = map[string]bool{
publishAttestationV01 + "a": true,
}

func Test_verifyName(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -963,17 +971,18 @@ func Test_verifyIntotoTypes(t *testing.T) {
t.Parallel()

tests := []struct {
name string
att *SignedAttestation
predicateType string
payloadType string
prefix bool
err error
name string
att *SignedAttestation
predicateType string
predicateTypes map[string]bool
payloadType string
prefix bool
err error
}{
{
name: "prov correct",
predicateType: common.ProvenanceV02Type,
payloadType: intoto.PayloadType,
name: "prov correct",
predicateTypes: provenancePredicates,
payloadType: intoto.PayloadType,
att: &SignedAttestation{
Envelope: &dsselib.Envelope{
PayloadType: "application/vnd.in-toto+json",
Expand All @@ -982,9 +991,9 @@ func Test_verifyIntotoTypes(t *testing.T) {
},
},
{
name: "prov mismatch payload type",
predicateType: common.ProvenanceV02Type,
payloadType: intoto.PayloadType,
name: "prov mismatch payload type",
predicateTypes: provenancePredicates,
payloadType: intoto.PayloadType,
att: &SignedAttestation{
Envelope: &dsselib.Envelope{
PayloadType: "application/vnd.in-toto+jso",
Expand All @@ -994,9 +1003,9 @@ func Test_verifyIntotoTypes(t *testing.T) {
err: serrors.ErrorInvalidDssePayload,
},
{
name: "prov mismatch predicate type",
predicateType: common.ProvenanceV02Type + "a",
payloadType: intoto.PayloadType,
name: "prov mismatch predicate type",
predicateTypes: mismatchProvenancePredicates,
payloadType: intoto.PayloadType,
att: &SignedAttestation{
Envelope: &dsselib.Envelope{
PayloadType: "application/vnd.in-toto+json",
Expand All @@ -1006,10 +1015,10 @@ func Test_verifyIntotoTypes(t *testing.T) {
err: serrors.ErrorInvalidDssePayload,
},
{
name: "publish correct",
predicateType: publishAttestationV01,
prefix: true,
payloadType: intoto.PayloadType,
name: "publish correct",
predicateTypes: publishPredicates,
prefix: true,
payloadType: intoto.PayloadType,
att: &SignedAttestation{
Envelope: &dsselib.Envelope{
PayloadType: "application/vnd.in-toto+json",
Expand All @@ -1018,10 +1027,10 @@ func Test_verifyIntotoTypes(t *testing.T) {
},
},
{
name: "publish mismatch payload type",
predicateType: publishAttestationV01,
prefix: true,
payloadType: intoto.PayloadType,
name: "publish mismatch payload type",
predicateTypes: publishPredicates,
prefix: true,
payloadType: intoto.PayloadType,
att: &SignedAttestation{
Envelope: &dsselib.Envelope{
PayloadType: "application/vnd.in-toto+jso",
Expand All @@ -1031,10 +1040,10 @@ func Test_verifyIntotoTypes(t *testing.T) {
err: serrors.ErrorInvalidDssePayload,
},
{
name: "publish mismatch predicate type",
predicateType: publishAttestationV01 + "a",
prefix: true,
payloadType: intoto.PayloadType,
name: "publish mismatch predicate type",
predicateTypes: mismatchPublishPredicates,
prefix: true,
payloadType: intoto.PayloadType,
att: &SignedAttestation{
Envelope: &dsselib.Envelope{
PayloadType: "application/vnd.in-toto+json",
Expand All @@ -1049,7 +1058,7 @@ func Test_verifyIntotoTypes(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

err := verifyIntotoTypes(tt.att, tt.predicateType, tt.payloadType, tt.prefix)
err := verifyIntotoTypes(tt.att, tt.predicateTypes, tt.payloadType, tt.prefix)
if !errCmp(err, tt.err) {
t.Errorf(cmp.Diff(err, tt.err))
}
Expand Down

0 comments on commit 99fc0bc

Please sign in to comment.