diff --git a/.github/workflows/pre-submit.e2e.yml b/.github/workflows/pre-submit.e2e.yml index 254a2d1..1883274 100644 --- a/.github/workflows/pre-submit.e2e.yml +++ b/.github/workflows/pre-submit.e2e.yml @@ -34,3 +34,5 @@ jobs: - name: Run verification script with testdata and slsa-verifier HEAD run: ./__THIS_REPO__/.github/workflows/scripts/e2e-cli.sh + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Necessary to use the gh CLI. diff --git a/.github/workflows/scripts/e2e-cli.sh b/.github/workflows/scripts/e2e-cli.sh index ab87d2e..6ff8c95 100755 --- a/.github/workflows/scripts/e2e-cli.sh +++ b/.github/workflows/scripts/e2e-cli.sh @@ -1,19 +1,42 @@ #!/bin/bash +repo="slsa-framework/example-package" +api_version="X-GitHub-Api-Version: 2022-11-28" # Verify provenance authenticity with slsa-verifier at HEAD +download_artifact(){ + local run_id="$1" + local artifact_name="$2" + # Get the artifact ID for 'artifact1' + artifact_id=$(gh api -H "Accept: application/vnd.github+json" -H "$api_version" "/repos/$repo/actions/runs/$run_id/artifacts" | jq ".artifacts[] | select(.name == \"$artifact_name\") | .id") + echo "artifact_id:$artifact_id" + + gh api -H "Accept: application/vnd.github+json" -H "$api_version" "/repos/$repo/actions/artifacts/$artifact_id/zip" > "$artifact_name.zip" + unzip "$artifact_name".zip +} + +# Get workflow ID. +workflow_id=$(gh api -H "Accept: application/vnd.github+json" -H "$api_version" "/repos/$repo/actions/workflows?per_page=100" | jq '.workflows[] | select(.path == ".github/workflows/e2e.generic.schedule.main.multi-uses.slsa3.yml") | .id') +echo "workflow_id:$workflow_id" + +# Get the run ID for the most recent run. +run_id=$(gh api -H "Accept: application/vnd.github+json" -H "$api_version" "/repos/$repo/actions/workflows/$workflow_id/runs?per_page=1" | jq '.workflow_runs[0].id') +echo "run_id:$run_id" + +download_artifact "$run_id" "artifacts1" +download_artifact "$run_id" "attestation1.intoto.jsonl" cd __EXAMPLE_PACKAGE__ # shellcheck source=/dev/null source "./.github/workflows/scripts/e2e-verify.common.sh" # Set THIS_FILE to correspond with the artifact properties -export THIS_FILE=e2e.go.workflow_dispatch.main.config-noldflags.slsa3.yml +export THIS_FILE=e2e.generic.schedule.main.multi-uses.slsa3.yml export BRANCH=main # Set BINARY and PROVENANCE cd - -export BINARY=__THIS_REPO__/cli/slsa-verifier/testdata/gha_go/v1.2.2/binary-linux-amd64-workflow_dispatch -export PROVENANCE=__THIS_REPO__/cli/slsa-verifier/testdata/gha_go/v1.2.2/binary-linux-amd64-workflow_dispatch.intoto.jsonl +export BINARY=artifact1 +export PROVENANCE=attestation1.intoto.jsonl -GITHUB_REPOSITORY=slsa-framework/example-package verify_provenance_authenticity "./__THIS_REPO__/slsa-verifier" "HEAD" +GITHUB_REPOSITORY="$repo" verify_provenance_authenticity "./__THIS_REPO__/slsa-verifier" "HEAD" diff --git a/cli/slsa-verifier/main.go b/cli/slsa-verifier/main.go index 41dcfa8..f41694a 100644 --- a/cli/slsa-verifier/main.go +++ b/cli/slsa-verifier/main.go @@ -29,6 +29,7 @@ For more information on SLSA, visit https://slsa.dev`, c.AddCommand(version.Version()) c.AddCommand(verifyArtifactCmd()) c.AddCommand(verifyImageCmd()) + c.AddCommand(verifyNpmPackageCmd()) // We print our own errors and usage in the check function. c.SilenceErrors = true return c diff --git a/cli/slsa-verifier/verify.go b/cli/slsa-verifier/verify.go index c9d6ce0..7d5a95b 100644 --- a/cli/slsa-verifier/verify.go +++ b/cli/slsa-verifier/verify.go @@ -121,3 +121,63 @@ func verifyImageCmd() *cobra.Command { o.AddFlags(cmd) return cmd } + +func verifyNpmPackageCmd() *cobra.Command { + o := &verify.VerifyNpmOptions{} + + cmd := &cobra.Command{ + Use: "verify-npm-package [flags] tarball", + Args: func(cmd *cobra.Command, args []string) error { + if len(args) != 1 { + return errors.New("expects a single path to an image") + } + return nil + }, + Short: "Verifies SLSA provenance for an npm package tarball [experimental]", + Run: func(cmd *cobra.Command, args []string) { + v := verify.VerifyNpmPackageCommand{ + SourceURI: o.SourceURI, + PrintProvenance: o.PrintProvenance, + BuildWorkflowInputs: o.BuildWorkflowInputs.AsMap(), + } + if cmd.Flags().Changed("attestations-path") { + v.AttestationsPath = o.AttestationsPath + } + if cmd.Flags().Changed("package-name") { + v.PackageName = &o.PackageName + } + if cmd.Flags().Changed("package-version") { + v.PackageVersion = &o.PackageVersion + } + if cmd.Flags().Changed("source-branch") { + fmt.Fprintf(os.Stderr, "%s: --source-branch not supported\n", FAILURE) + os.Exit(1) + } + if cmd.Flags().Changed("source-tag") { + fmt.Fprintf(os.Stderr, "%s: --source-tag not supported\n", FAILURE) + os.Exit(1) + } + if cmd.Flags().Changed("source-versioned-tag") { + fmt.Fprintf(os.Stderr, "%s: --source-versioned-tag not supported\n", FAILURE) + os.Exit(1) + } + if cmd.Flags().Changed("print-provenance") { + fmt.Fprintf(os.Stderr, "%s: --print-provenance not supported\n", FAILURE) + os.Exit(1) + } + if cmd.Flags().Changed("builder-id") { + v.BuilderID = &o.BuilderID + } + + if _, err := v.Exec(cmd.Context(), args); err != nil { + fmt.Fprintf(os.Stderr, "%s: %v\n", FAILURE, err) + os.Exit(1) + } else { + fmt.Fprintf(os.Stderr, "%s\n", SUCCESS) + } + }, + } + + o.AddFlags(cmd) + return cmd +} diff --git a/cli/slsa-verifier/verify/options.go b/cli/slsa-verifier/verify/options.go index f860cb1..faf06a8 100644 --- a/cli/slsa-verifier/verify/options.go +++ b/cli/slsa-verifier/verify/options.go @@ -74,6 +74,52 @@ func (o *VerifyOptions) AddFlags(cmd *cobra.Command) { cmd.MarkFlagsMutuallyExclusive("source-versioned-tag", "source-tag") } +// VerifyNpmOptions is the top-level options for the `verifyNpmPackage` command. +type VerifyNpmOptions struct { + VerifyOptions + /* Other */ + AttestationsPath string + PackageName string + PackageVersion string +} + +var _ Interface = (*VerifyNpmOptions)(nil) + +// AddFlags implements Interface. +func (o *VerifyNpmOptions) AddFlags(cmd *cobra.Command) { + /* Builder options */ + cmd.Flags().Var(&o.BuildWorkflowInputs, "build-workflow-input", + "[optional] a workflow input provided by a user at trigger time in the format 'key=value'. (Only for 'workflow_dispatch' events on GitHub Actions).") + + cmd.Flags().StringVar(&o.BuilderID, "builder-id", "", "[optional] the unique builder ID who created the provenance") + + /* Source options */ + cmd.Flags().StringVar(&o.SourceURI, "source-uri", "", + "expected source repository that should have produced the binary, e.g. github.com/some/repo") + + cmd.Flags().StringVar(&o.SourceBranch, "source-branch", "", "[optional] expected branch the binary was compiled from") + + cmd.Flags().StringVar(&o.SourceTag, "source-tag", "", "[optional] expected tag the binary was compiled from") + + cmd.Flags().StringVar(&o.SourceVersionTag, "source-versioned-tag", "", + "[optional] expected version the binary was compiled from. Uses semantic version to match the tag") + + cmd.Flags().StringVar(&o.AttestationsPath, "attestations-path", "", + "path to a file containing the attestations") + + cmd.Flags().StringVar(&o.PackageName, "package-name", "", + "[optional] the package name") + + cmd.Flags().StringVar(&o.PackageVersion, "package-version", "", + "[optional] the package version") + + cmd.Flags().BoolVar(&o.PrintProvenance, "print-provenance", false, + "[optional] print the verified provenance to stdout") + + cmd.MarkFlagRequired("source-uri") + cmd.MarkFlagsMutuallyExclusive("source-versioned-tag", "source-tag") +} + type workflowInputs struct { kv map[string]string } diff --git a/cli/slsa-verifier/verify/utils.go b/cli/slsa-verifier/verify/utils.go new file mode 100644 index 0000000..065e924 --- /dev/null +++ b/cli/slsa-verifier/verify/utils.go @@ -0,0 +1,35 @@ +// Copyright 2023 SLSA Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package verify + +import ( + "encoding/hex" + "hash" + "io" + "os" +) + +func computeFileHash(filePath string, h hash.Hash) (string, error) { + f, err := os.Open(filePath) + if err != nil { + return "", err + } + defer f.Close() + + if _, err := io.Copy(h, f); err != nil { + return "", err + } + return hex.EncodeToString(h.Sum(nil)), nil +} diff --git a/cli/slsa-verifier/verify/verify_artifact.go b/cli/slsa-verifier/verify/verify_artifact.go index 0a3e854..d6fb4ec 100644 --- a/cli/slsa-verifier/verify/verify_artifact.go +++ b/cli/slsa-verifier/verify/verify_artifact.go @@ -17,9 +17,7 @@ package verify import ( "context" "crypto/sha256" - "encoding/hex" "fmt" - "io" "os" "github.com/slsa-framework/slsa-verifier/v2/options" @@ -43,7 +41,7 @@ func (c *VerifyArtifactCommand) Exec(ctx context.Context, artifacts []string) (* var builderID *utils.TrustedBuilderID for _, artifact := range artifacts { - artifactHash, err := getArtifactHash(artifact) + artifactHash, err := computeFileHash(artifact, sha256.New()) if err != nil { fmt.Fprintf(os.Stderr, "Verifying artifact %s: FAILED: %v\n\n", artifact, err) return nil, err @@ -90,16 +88,3 @@ func (c *VerifyArtifactCommand) Exec(ctx context.Context, artifacts []string) (* return builderID, nil } - -func getArtifactHash(artifactPath string) (string, error) { - f, err := os.Open(artifactPath) - if err != nil { - return "", err - } - defer f.Close() - h := sha256.New() - if _, err := io.Copy(h, f); err != nil { - return "", err - } - return hex.EncodeToString(h.Sum(nil)), nil -} diff --git a/cli/slsa-verifier/verify/verify_npm_package.go b/cli/slsa-verifier/verify/verify_npm_package.go new file mode 100644 index 0000000..666fb01 --- /dev/null +++ b/cli/slsa-verifier/verify/verify_npm_package.go @@ -0,0 +1,96 @@ +// Copyright 2022 SLSA Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package verify + +import ( + "context" + "crypto/sha512" + "errors" + "fmt" + "os" + + "github.com/slsa-framework/slsa-verifier/v2/options" + "github.com/slsa-framework/slsa-verifier/v2/verifiers" + "github.com/slsa-framework/slsa-verifier/v2/verifiers/utils" +) + +type VerifyNpmPackageCommand struct { + AttestationsPath string + BuilderID *string + SourceURI string + SourceBranch *string + SourceTag *string + SourceVersionTag *string + PackageName *string + PackageVersion *string + BuildWorkflowInputs map[string]string + PrintProvenance bool +} + +func (c *VerifyNpmPackageCommand) Exec(ctx context.Context, tarballs []string) (*utils.TrustedBuilderID, error) { + var builderID *utils.TrustedBuilderID + if !options.ExperimentalEnabled() { + err := errors.New("feature support is only provided in SLSA_VERIFIER_EXPERIMENTAL mode") + fmt.Fprintf(os.Stderr, "Verifying npm package: FAILED: %v\n\n", err) + return nil, err + } + for _, tarball := range tarballs { + tarballHash, err := computeFileHash(tarball, sha512.New()) + if err != nil { + fmt.Fprintf(os.Stderr, "Verifying npm package %s: FAILED: %v\n\n", tarball, err) + return nil, err + } + + if c.AttestationsPath == "" { + fmt.Fprintf(os.Stderr, "Verifying npm package %s: FAILED: %v\n\n", tarball, err) + return nil, err + } + provenanceOpts := &options.ProvenanceOpts{ + ExpectedSourceURI: c.SourceURI, + ExpectedBranch: c.SourceBranch, + ExpectedDigest: tarballHash, + ExpectedVersionedTag: c.SourceVersionTag, + ExpectedTag: c.SourceTag, + ExpectedWorkflowInputs: c.BuildWorkflowInputs, + ExpectedPackageName: c.PackageName, + ExpectedPackageVersion: c.PackageVersion, + } + + builderOpts := &options.BuilderOpts{ + ExpectedID: c.BuilderID, + } + + attestations, err := os.ReadFile(c.AttestationsPath) + if err != nil { + fmt.Fprintf(os.Stderr, "Verifying npm package %s: FAILED: %v\n\n", tarball, err) + return nil, err + } + + verifiedProvenance, outBuilderID, err := verifiers.VerifyNpmPackage(ctx, attestations, tarballHash, provenanceOpts, builderOpts) + if err != nil { + fmt.Fprintf(os.Stderr, "Verifying npm package %s: FAILED: %v\n\n", tarball, err) + return nil, err + } + + if c.PrintProvenance { + fmt.Fprintf(os.Stdout, "%s\n", string(verifiedProvenance)) + } + + builderID = outBuilderID + fmt.Fprintf(os.Stderr, "Verifying npm package %s: PASSED\n\n", tarball) + } + + return builderID, nil +} diff --git a/errors/errors.go b/errors/errors.go index eb4b644..403004a 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -5,6 +5,8 @@ import "errors" var ( ErrorInvalidDssePayload = errors.New("invalid DSSE envelope payload") ErrorMismatchBranch = errors.New("branch used to generate the binary does not match provenance") + ErrorMismatchPackageVersion = errors.New("package version does not match provenance") + ErrorMismatchPackageName = errors.New("package name does not match provenance") ErrorMismatchBuilderID = errors.New("builderID does not match provenance") ErrorInvalidBuilderID = errors.New("builderID is invalid") ErrorMismatchSource = errors.New("source used to generate the binary does not match provenance") @@ -33,4 +35,6 @@ var ( ErrorInternal = errors.New("internal error") ErrorInvalidRekorEntry = errors.New("invalid Rekor entry") ErrorRekorPubKey = errors.New("error retrieving Rekor public keys") + ErrorInvalidPackageName = errors.New("invalid package name") + ErrorInvalidSubject = errors.New("invalid subject") ) diff --git a/options/options.go b/options/options.go index f5cd591..7bc9c46 100644 --- a/options/options.go +++ b/options/options.go @@ -23,6 +23,10 @@ type ProvenanceOpts struct { // ExpectedWorkflowInputs is a map of key=value inputs. ExpectedWorkflowInputs map[string]string + + ExpectedPackageName *string + + ExpectedPackageVersion *string } // BuildOpts are the options for checking the builder. diff --git a/register/register.go b/register/register.go index d3eb53a..787bb1f 100644 --- a/register/register.go +++ b/register/register.go @@ -28,6 +28,12 @@ type SLSAVerifier interface { provenanceOpts *options.ProvenanceOpts, builderOpts *options.BuilderOpts, ) ([]byte, *utils.TrustedBuilderID, error) + + VerifyNpmPackage(ctx context.Context, + attestations []byte, tarballHash string, + provenanceOpts *options.ProvenanceOpts, + builderOpts *options.BuilderOpts, + ) ([]byte, *utils.TrustedBuilderID, error) } func RegisterVerifier(name string, verifier SLSAVerifier) { diff --git a/verifiers/internal/gcb/provenance.go b/verifiers/internal/gcb/provenance.go index 308fef8..c0a14ab 100644 --- a/verifiers/internal/gcb/provenance.go +++ b/verifiers/internal/gcb/provenance.go @@ -2,7 +2,6 @@ package gcb import ( "crypto/sha256" - "encoding/base64" "encoding/json" "fmt" "os" @@ -79,17 +78,6 @@ func ProvenanceFromBytes(payload []byte) (*Provenance, error) { }, nil } -func payloadFromEnvelope(env *dsselib.Envelope) ([]byte, error) { - payload, err := base64.StdEncoding.DecodeString(env.Payload) - if err != nil { - return nil, fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, err.Error()) - } - if payload == nil { - return nil, fmt.Errorf("%w: empty payload", serrors.ErrorInvalidFormat) - } - return payload, nil -} - func (p *Provenance) isVerified() error { // Check that the signature is verified. if p.verifiedIntotoStatement == nil || @@ -413,31 +401,6 @@ func (p *Provenance) VerifyVersionedTag(tag string) error { return fmt.Errorf("%w: GCB versioned-tag verification", serrors.ErrorNotSupported) } -func decodeSignature(s string) ([]byte, error) { - var errs []error - // First try the std decoding. - rsig, err := base64.StdEncoding.DecodeString(s) - if err == nil { - // No error, return the value. - return rsig, nil - } - errs = append(errs, err) - - // If std decoding failed, try URL decoding. - // We try both because we encountered decoding failures - // during our tests. The DSSE documentation does not prescribe - // which encoding to use: `Either standard or URL-safe encoding is allowed`. - // https://github.com/secure-systems-lab/dsse/blob/27ce241dec575998dee8967c3c76d4edd5d6ee73/envelope.md#standard-json-envelope. - rsig, err = base64.URLEncoding.DecodeString(s) - if err == nil { - // No error, return the value. - return rsig, nil - } - errs = append(errs, err) - - return nil, fmt.Errorf("%w: %v", serrors.ErrorInvalidEncoding, errs) -} - // verifySignatures iterates over all the signatures in the DSSE and verifies them. // It succeeds if one of them can be verified. func (p *Provenance) verifySignatures(prov *provenance) error { @@ -447,7 +410,7 @@ func (p *Provenance) verifySignatures(prov *provenance) error { serrors.ErrorInvalidDssePayload, intoto.PayloadType, prov.Envelope.PayloadType) } - payload, err := payloadFromEnvelope(&prov.Envelope) + payload, err := utils.PayloadFromEnvelope(&prov.Envelope) if err != nil { return err } @@ -473,7 +436,7 @@ func (p *Provenance) verifySignatures(prov *provenance) error { } // Decode the signature. - rsig, err := decodeSignature(sig.Sig) + rsig, err := utils.DecodeSignature(sig.Sig) if err != nil { errs = append(errs, err) continue diff --git a/verifiers/internal/gcb/provenance_test.go b/verifiers/internal/gcb/provenance_test.go index e156d76..d60e763 100644 --- a/verifiers/internal/gcb/provenance_test.go +++ b/verifiers/internal/gcb/provenance_test.go @@ -21,7 +21,7 @@ import ( // after the signature is verified. func setStatement(gcb *Provenance) error { var statement v01IntotoStatement - payload, err := payloadFromEnvelope(&gcb.gcloudProv.ProvenanceSummary.Provenance[0].Envelope) + payload, err := utils.PayloadFromEnvelope(&gcb.gcloudProv.ProvenanceSummary.Provenance[0].Envelope) if err != nil { return fmt.Errorf("payloadFromEnvelope: %w", err) } @@ -311,51 +311,6 @@ func Test_validateRecipeType(t *testing.T) { } } -func Test_decodeSignature(t *testing.T) { - t.Parallel() - tests := []struct { - name string - encoded string - decoded string - expected error - }{ - { - name: "std encoding", - encoded: "YWJjMTIzIT8kKiYoKSctPUB+", - decoded: "abc123!?$*&()'-=@~", - }, - { - name: "URL encoding", - encoded: "YWJjMTIzIT8kKiYoKSctPUB-", - decoded: "abc123!?$*&()'-=@~", - }, - { - name: "invalid", - encoded: "invalid encoding", - expected: serrors.ErrorInvalidEncoding, - }, - } - - for _, tt := range tests { - tt := tt // Re-initializing variable so it is not changed while executing the closure below - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - c, err := decodeSignature(tt.encoded) - if !cmp.Equal(err, tt.expected, cmpopts.EquateErrors()) { - t.Errorf(cmp.Diff(err, tt.expected, cmpopts.EquateErrors())) - } - if err != nil { - return - } - cs := string(c) - if cs != tt.decoded { - t.Errorf(cmp.Diff(cs, tt.decoded)) - } - }) - } -} - func Test_VerifySourceURI(t *testing.T) { t.Parallel() tests := []struct { diff --git a/verifiers/internal/gcb/verifier.go b/verifiers/internal/gcb/verifier.go index de5d775..04f31e6 100644 --- a/verifiers/internal/gcb/verifier.go +++ b/verifiers/internal/gcb/verifier.go @@ -39,6 +39,15 @@ func (v *GCBVerifier) VerifyArtifact(ctx context.Context, return nil, nil, serrors.ErrorNotSupported } +// VerifyNpmPackage verifies an npm package tarball. +func (v *GCBVerifier) VerifyNpmPackage(ctx context.Context, + attestations []byte, tarballHash string, + provenanceOpts *options.ProvenanceOpts, + builderOpts *options.BuilderOpts, +) ([]byte, *utils.TrustedBuilderID, error) { + return nil, nil, serrors.ErrorNotSupported +} + // VerifyImage verifies provenance for an OCI image. func (v *GCBVerifier) VerifyImage(ctx context.Context, provenance []byte, artifactImage string, diff --git a/verifiers/internal/gha/builder.go b/verifiers/internal/gha/builder.go index 423fc0e..01193c7 100644 --- a/verifiers/internal/gha/builder.go +++ b/verifiers/internal/gha/builder.go @@ -32,13 +32,39 @@ var defaultContainerTrustedReusableWorkflows = map[string]bool{ trustedBuilderRepository + "/.github/workflows/generator_container_slsa3.yml": true, } -// VerifyWorkflowIdentity verifies the signing certificate information +var defaultBYOBReusableWorkflows = map[string]bool{ + trustedBuilderRepository + "/.github/workflows/delegator_generic_slsa3.yml": true, +} + +// VerifyCertficateSourceRepository verifies the source repository. +func VerifyCertficateSourceRepository(id *WorkflowIdentity, + sourceRepo string, +) error { + // The caller repository in the x509 extension is not fully qualified. It only contains + // {org}/{repository}. + expectedSource := strings.TrimPrefix(sourceRepo, "git+https://") + expectedSource = strings.TrimPrefix(expectedSource, "github.com/") + if id.CallerRepository != expectedSource { + return fmt.Errorf("%w: expected source '%s', got '%s'", serrors.ErrorMismatchSource, + expectedSource, id.CallerRepository) + } + return nil +} + +// VerifyBuilderIdentity verifies the signing certificate information. // Builder IDs are verified against an expected builder ID provided in the -// builerOpts, or against the set of defaultBuilders provided. -func VerifyWorkflowIdentity(id *WorkflowIdentity, - builderOpts *options.BuilderOpts, source string, +// builerOpts, or against the set of defaultBuilders provided. The identiy +// in the certificate corresponds to a GitHub workflow's path. +func VerifyBuilderIdentity(id *WorkflowIdentity, + builderOpts *options.BuilderOpts, defaultBuilders map[string]bool, ) (*utils.TrustedBuilderID, error) { + // Issuer verification. + // NOTE: this is necessary before we do any further verification. + if id.Issuer != certOidcIssuer { + return nil, fmt.Errorf("%w: %s", serrors.ErrorInvalidOIDCIssuer, id.Issuer) + } + // cert URI path is /org/repo/path/to/workflow@ref workflowPath := strings.SplitN(id.JobWobWorkflowRef, "@", 2) if len(workflowPath) < 2 { @@ -59,22 +85,6 @@ func VerifyWorkflowIdentity(id *WorkflowIdentity, return nil, err } - // Issuer verification. - if !strings.EqualFold(id.Issuer, certOidcIssuer) { - return nil, fmt.Errorf("%w: %s", serrors.ErrorInvalidOIDCIssuer, id.Issuer) - } - - // The caller repository in the x509 extension is not fully qualified. It only contains - // {org}/{repository}. - expectedSource := strings.TrimPrefix(source, "git+https://") - expectedSource = strings.TrimPrefix(expectedSource, "github.com/") - if !strings.EqualFold(id.CallerRepository, expectedSource) { - return nil, fmt.Errorf("%w: expected source '%s', got '%s'", serrors.ErrorMismatchSource, - expectedSource, id.CallerRepository) - } - - // Return the builder and its tag. - // Note: the tag has the format `refs/tags/v1.2.3`. return builderID, nil } diff --git a/verifiers/internal/gha/builder_test.go b/verifiers/internal/gha/builder_test.go index 8dac4bd..cf83bc6 100644 --- a/verifiers/internal/gha/builder_test.go +++ b/verifiers/internal/gha/builder_test.go @@ -10,7 +10,7 @@ import ( "github.com/slsa-framework/slsa-verifier/v2/options" ) -func Test_VerifyWorkflowIdentity(t *testing.T) { +func Test_VerifyBuilderIdentity(t *testing.T) { t.Parallel() tests := []struct { name string @@ -18,7 +18,6 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { buildOpts *options.BuilderOpts builderID string defaults map[string]bool - source string err error }{ { @@ -30,7 +29,6 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { Trigger: "workflow_dispatch", Issuer: "https://token.actions.githubusercontent.com", }, - source: "asraa/slsa-on-github-test", defaults: defaultArtifactTrustedReusableWorkflows, err: serrors.ErrorMalformedURI, }, @@ -43,7 +41,6 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { Trigger: "workflow_dispatch", Issuer: "https://token.actions.githubusercontent.com", }, - source: "asraa/slsa-on-github-test", defaults: defaultArtifactTrustedReusableWorkflows, err: serrors.ErrorUntrustedReusableWorkflow, }, @@ -54,9 +51,8 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { CallerHash: "0dfcd24824432c4ce587f79c918eef8fc2c44d7b", JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/heads/main", Trigger: "workflow_dispatch", - Issuer: "https://bad.issuer.com", + Issuer: "https://token.actions.githubusercontent.com", }, - source: "asraa/slsa-on-github-test", defaults: defaultArtifactTrustedReusableWorkflows, err: serrors.ErrorInvalidRef, }, @@ -69,7 +65,6 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { Trigger: "workflow_dispatch", Issuer: "https://bad.issuer.com", }, - source: "asraa/slsa-on-github-test", defaults: defaultArtifactTrustedReusableWorkflows, err: serrors.ErrorInvalidOIDCIssuer, }, @@ -82,7 +77,6 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { Trigger: "workflow_dispatch", Issuer: "https://token.actions.githubusercontent.com", }, - source: trustedBuilderRepository, defaults: defaultArtifactTrustedReusableWorkflows, builderID: "https://github.com/" + trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml", }, @@ -95,7 +89,6 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { Trigger: "workflow_dispatch", Issuer: certOidcIssuer, }, - source: e2eTestRepository, defaults: defaultArtifactTrustedReusableWorkflows, builderID: "https://github.com/" + trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml", }, @@ -108,7 +101,6 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { Trigger: "workflow_dispatch", Issuer: certOidcIssuer, }, - source: e2eTestRepository, buildOpts: &options.BuilderOpts{ ExpectedID: asStringPointer("https://github.com/" + trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml"), }, @@ -124,65 +116,12 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { Trigger: "workflow_dispatch", Issuer: certOidcIssuer, }, - source: e2eTestRepository, buildOpts: &options.BuilderOpts{ ExpectedID: asStringPointer("some-other-builderID"), }, defaults: defaultArtifactTrustedReusableWorkflows, err: serrors.ErrorUntrustedReusableWorkflow, }, - { - name: "unexpected source for e2e test", - workflow: &WorkflowIdentity{ - CallerRepository: e2eTestRepository, - CallerHash: "0dfcd24824432c4ce587f79c918eef8fc2c44d7b", - JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/tags/v1.2.3", - Trigger: "workflow_dispatch", - Issuer: certOidcIssuer, - }, - source: "malicious/source", - err: serrors.ErrorMismatchSource, - defaults: defaultArtifactTrustedReusableWorkflows, - builderID: "https://github.com/" + trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml", - }, - { - name: "valid main ref for builder", - workflow: &WorkflowIdentity{ - CallerRepository: trustedBuilderRepository, - JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/tags/v1.2.3", - Trigger: "workflow_dispatch", - Issuer: certOidcIssuer, - }, - source: "malicious/source", - defaults: defaultArtifactTrustedReusableWorkflows, - err: serrors.ErrorMismatchSource, - }, - { - name: "unexpected source", - workflow: &WorkflowIdentity{ - CallerRepository: "malicious/slsa-on-github-test", - CallerHash: "0dfcd24824432c4ce587f79c918eef8fc2c44d7b", - JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/tags/v1.2.3", - Trigger: "workflow_dispatch", - Issuer: certOidcIssuer, - }, - source: "asraa/slsa-on-github-test", - defaults: defaultArtifactTrustedReusableWorkflows, - err: serrors.ErrorMismatchSource, - }, - { - name: "valid workflow identity", - workflow: &WorkflowIdentity{ - CallerRepository: "asraa/slsa-on-github-test", - CallerHash: "0dfcd24824432c4ce587f79c918eef8fc2c44d7b", - JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/tags/v1.2.3", - Trigger: "workflow_dispatch", - Issuer: certOidcIssuer, - }, - source: "asraa/slsa-on-github-test", - defaults: defaultArtifactTrustedReusableWorkflows, - builderID: "https://github.com/" + trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml", - }, { name: "valid workflow identity - match builderID", workflow: &WorkflowIdentity{ @@ -192,7 +131,6 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { Trigger: "workflow_dispatch", Issuer: certOidcIssuer, }, - source: "asraa/slsa-on-github-test", buildOpts: &options.BuilderOpts{ ExpectedID: asStringPointer("https://github.com/" + trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml"), }, @@ -208,7 +146,6 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { Trigger: "workflow_dispatch", Issuer: certOidcIssuer, }, - source: "asraa/slsa-on-github-test", buildOpts: &options.BuilderOpts{ ExpectedID: asStringPointer("some-other-builderID"), }, @@ -224,7 +161,6 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { Trigger: "workflow_dispatch", Issuer: certOidcIssuer, }, - source: "asraa/slsa-on-github-test", err: serrors.ErrorInvalidRef, defaults: defaultArtifactTrustedReusableWorkflows, builderID: "https://github.com/" + trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml", @@ -238,7 +174,6 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { Trigger: "workflow_dispatch", Issuer: certOidcIssuer, }, - source: "asraa/slsa-on-github-test", defaults: defaultArtifactTrustedReusableWorkflows, err: serrors.ErrorInvalidRef, }, @@ -251,7 +186,6 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { Trigger: "workflow_dispatch", Issuer: certOidcIssuer, }, - source: "asraa/slsa-on-github-test", defaults: defaultArtifactTrustedReusableWorkflows, err: serrors.ErrorInvalidRef, }, @@ -264,7 +198,6 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { Trigger: "workflow_dispatch", Issuer: certOidcIssuer, }, - source: "github.com/asraa/slsa-on-github-test", defaults: defaultArtifactTrustedReusableWorkflows, builderID: "https://github.com/" + trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml", }, @@ -277,7 +210,6 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { Trigger: "workflow_dispatch", Issuer: certOidcIssuer, }, - source: "github.com/asraa/slsa-on-github-test", buildOpts: &options.BuilderOpts{ ExpectedID: asStringPointer("https://github.com/" + trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml"), }, @@ -292,7 +224,6 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { Trigger: "workflow_dispatch", Issuer: certOidcIssuer, }, - source: "github.com/asraa/slsa-on-github-test", buildOpts: &options.BuilderOpts{ ExpectedID: asStringPointer("https://github.com/" + trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml"), }, @@ -308,7 +239,6 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { Trigger: "workflow_dispatch", Issuer: certOidcIssuer, }, - source: "github.com/asraa/slsa-on-github-test", buildOpts: &options.BuilderOpts{ ExpectedID: asStringPointer("some-other-builderID"), }, @@ -324,7 +254,6 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { Trigger: "workflow_dispatch", Issuer: certOidcIssuer, }, - source: "github.com/asraa/slsa-on-github-test", defaults: defaultContainerTrustedReusableWorkflows, err: serrors.ErrorUntrustedReusableWorkflow, }, @@ -337,8 +266,7 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { if opts == nil { opts = &options.BuilderOpts{} } - id, err := VerifyWorkflowIdentity(tt.workflow, opts, tt.source, - tt.defaults) + id, err := VerifyBuilderIdentity(tt.workflow, opts, tt.defaults) if !errCmp(err, tt.err) { t.Errorf(cmp.Diff(err, tt.err, cmpopts.EquateErrors())) } @@ -353,6 +281,73 @@ func Test_VerifyWorkflowIdentity(t *testing.T) { } } +func Test_VerifyCertficateSourceRepository(t *testing.T) { + t.Parallel() + tests := []struct { + name string + workflow *WorkflowIdentity + source string + err error + }{ + { + name: "repo match", + workflow: &WorkflowIdentity{ + CallerRepository: "asraa/slsa-on-github-test", + CallerHash: "0dfcd24824432c4ce587f79c918eef8fc2c44d7b", + JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/tags/v1.2.3", + Trigger: "workflow_dispatch", + Issuer: certOidcIssuer, + }, + source: "github.com/asraa/slsa-on-github-test", + }, + { + name: "unexpected source for e2e test", + workflow: &WorkflowIdentity{ + CallerRepository: e2eTestRepository, + CallerHash: "0dfcd24824432c4ce587f79c918eef8fc2c44d7b", + JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/tags/v1.2.3", + Trigger: "workflow_dispatch", + Issuer: certOidcIssuer, + }, + source: "malicious/source", + err: serrors.ErrorMismatchSource, + }, + { + name: "valid main ref for builder", + workflow: &WorkflowIdentity{ + CallerRepository: trustedBuilderRepository, + JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/tags/v1.2.3", + Trigger: "workflow_dispatch", + Issuer: certOidcIssuer, + }, + source: "malicious/source", + err: serrors.ErrorMismatchSource, + }, + { + name: "unexpected source", + workflow: &WorkflowIdentity{ + CallerRepository: "malicious/slsa-on-github-test", + CallerHash: "0dfcd24824432c4ce587f79c918eef8fc2c44d7b", + JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/tags/v1.2.3", + Trigger: "workflow_dispatch", + Issuer: certOidcIssuer, + }, + source: "asraa/slsa-on-github-test", + err: serrors.ErrorMismatchSource, + }, + } + for _, tt := range tests { + tt := tt // Re-initializing variable so it is not changed while executing the closure below + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + err := VerifyCertficateSourceRepository(tt.workflow, tt.source) + if !errCmp(err, tt.err) { + t.Errorf(cmp.Diff(err, tt.err, cmpopts.EquateErrors())) + } + }) + } +} + func asStringPointer(s string) *string { return &s } diff --git a/verifiers/internal/gha/bundle.go b/verifiers/internal/gha/bundle.go index 7b52f89..4950e48 100644 --- a/verifiers/internal/gha/bundle.go +++ b/verifiers/internal/gha/bundle.go @@ -37,7 +37,8 @@ func IsSigstoreBundle(bytes []byte) bool { // bundle verification material, validating the SignedEntryTimestamp. func verifyRekorEntryFromBundle(ctx context.Context, tlogEntry *v1.TransparencyLogEntry, trustedRoot *TrustedRoot) ( - *models.LogEntryAnon, error) { + *models.LogEntryAnon, error, +) { canonicalBody := tlogEntry.GetCanonicalizedBody() logID := hex.EncodeToString(tlogEntry.GetLogId().GetKeyId()) rekorEntry := &models.LogEntryAnon{ @@ -78,6 +79,19 @@ func getEnvelopeFromBundle(bundle *bundle_v1.Bundle) (*dsselib.Envelope, error) return env, nil } +func getEnvelopeFromBundleBytes(content []byte) (*dsselib.Envelope, error) { + var bundle bundle_v1.Bundle + if err := protojson.Unmarshal(content, &bundle); err != nil { + return nil, fmt.Errorf("unmarshaling bundle: %w", err) + } + env, err := getEnvelopeFromBundle(&bundle) + if err != nil { + return nil, err + } + + return env, nil +} + // getLeafCertFromBundle extracts the signing cert from the Sigstore bundle. func getLeafCertFromBundle(bundle *bundle_v1.Bundle) (*x509.Certificate, error) { certChain := bundle.GetVerificationMaterial().GetX509CertificateChain().GetCertificates() @@ -122,6 +136,7 @@ func matchRekorEntryWithEnvelope(tlogEntry *v1.TransparencyLogEntry, env *dsseli len(intotoObj.Content.Envelope.Signatures)) } + // TODO(#487): verify the certs match. for _, sig := range env.Signatures { // The signature in the canonical body is double base64-encoded. encodedEnvSig := base64.StdEncoding.EncodeToString( @@ -136,6 +151,7 @@ func matchRekorEntryWithEnvelope(tlogEntry *v1.TransparencyLogEntry, env *dsseli return ErrorMismatchSignature } } + return nil } @@ -144,13 +160,24 @@ func matchRekorEntryWithEnvelope(tlogEntry *v1.TransparencyLogEntry, env *dsseli // and the signing certificate given the provenance. func VerifyProvenanceBundle(ctx context.Context, bundleBytes []byte, trustedRoot *TrustedRoot) ( - *SignedAttestation, error) { - // Extract the SigningCert, Envelope, and RekorEntry from the bundle. - var bundle bundle_v1.Bundle - if err := protojson.Unmarshal(bundleBytes, &bundle); err != nil { - return nil, fmt.Errorf("unmarshaling bundle: %w", err) + *SignedAttestation, error, +) { + proposedSignedAtt, err := verifyBundleAndEntryFromBytes(ctx, bundleBytes, trustedRoot, true) + if err != nil { + return nil, err + } + if err := verifySignedAttestation(proposedSignedAtt, trustedRoot); err != nil { + return nil, err } + return proposedSignedAtt, nil +} + +// verifyBundleAndEntry validates the rekor entry inn the bundle +// and that the entry (cert, signatures) matches the data in the bundle. +func verifyBundleAndEntry(ctx context.Context, bundle *bundle_v1.Bundle, + trustedRoot *TrustedRoot, requireCert bool, +) (*SignedAttestation, error) { // We only expect one TLOG entry. If this changes in the future, we must iterate // for a matching one. if bundle.GetVerificationMaterial() == nil || @@ -166,7 +193,7 @@ func VerifyProvenanceBundle(ctx context.Context, bundleBytes []byte, } // Extract DSSE envelope. - env, err := getEnvelopeFromBundle(&bundle) + env, err := getEnvelopeFromBundle(bundle) if err != nil { return nil, err } @@ -177,20 +204,32 @@ func VerifyProvenanceBundle(ctx context.Context, bundleBytes []byte, } // Get certificate from bundle. - cert, err := getLeafCertFromBundle(&bundle) - if err != nil { - return nil, err + var cert *x509.Certificate + if requireCert { + cert, err = getLeafCertFromBundle(bundle) + if err != nil { + return nil, err + } } - proposedSignedAtt := &SignedAttestation{ + return &SignedAttestation{ SigningCert: cert, Envelope: env, RekorEntry: rekorEntry, - } - - if err := verifySignedAttestation(proposedSignedAtt, trustedRoot); err != nil { - return nil, err - } - - return proposedSignedAtt, nil + }, nil +} + +// verifyBundleAndEntryFromBytes validates the rekor entry inn the bundle +// and that the entry (cert, signatures) matches the data in the bundle. +func verifyBundleAndEntryFromBytes(ctx context.Context, bundleBytes []byte, + trustedRoot *TrustedRoot, requireCert bool, +) (*SignedAttestation, error) { + // Extract the SigningCert, Envelope, and RekorEntry from the bundle. + var bundle bundle_v1.Bundle + if err := protojson.Unmarshal(bundleBytes, &bundle); err != nil { + return nil, fmt.Errorf("unmarshaling bundle: %w", err) + } + + return verifyBundleAndEntry(ctx, &bundle, + trustedRoot, requireCert) } diff --git a/verifiers/internal/gha/npm.go b/verifiers/internal/gha/npm.go new file mode 100644 index 0000000..873671f --- /dev/null +++ b/verifiers/internal/gha/npm.go @@ -0,0 +1,465 @@ +package gha + +import ( + "context" + "crypto/ecdsa" + "crypto/sha256" + "crypto/x509" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "net/url" + "strings" + + intoto "github.com/in-toto/in-toto-golang/in_toto" + "github.com/secure-systems-lab/go-securesystemslib/dsse" + serrors "github.com/slsa-framework/slsa-verifier/v2/errors" + "github.com/slsa-framework/slsa-verifier/v2/verifiers/internal/gha/slsaprovenance" + "github.com/slsa-framework/slsa-verifier/v2/verifiers/utils" +) + +const ( + publishAttestationV01 = "https://github.com/npm/attestation/tree/main/specs/publish/" +) + +var errrorInvalidAttestations = errors.New("invalid npm attestations") + +/* +NOTE: key available at https://registry.npmjs.org/-/npm/v1/keys + + https://docs.npmjs.com/about-registry-signatures + { + "keys": [ + { + "expires": null, + "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA", + "keytype": "ecdsa-sha2-nistp256", + "scheme": "ecdsa-sha2-nistp256", + "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1Olb3zMAFFxXKHiIkQO5cJ3Yhl5i6UPp+IhuteBJbuHcA5UogKo0EWtlWwW6KSaKoTNEYL7JlCQiVnkhBktUgg==" + } + ] + } +*/ +var npmRegistryPublicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1Olb3zMAFFxXKHiIkQO5cJ3Yhl5i6UPp+IhuteBJbuHcA5UogKo0EWtlWwW6KSaKoTNEYL7JlCQiVnkhBktUgg==" + +type attestation struct { + PredicateType string `json:"predicateType"` + BundleBytes BundleBytes `json:"bundle"` +} + +type BundleBytes []byte + +func (b *BundleBytes) UnmarshalJSON(data []byte) error { + *b = data + return nil +} + +type Npm struct { + ctx context.Context + root *TrustedRoot + verifiedProvenanceAtt *SignedAttestation + verifiedPublishAtt *SignedAttestation + provenanceAttestation *attestation + publishAttestation *attestation +} + +// TODO(#494): update the builder name. +var builderGitHubRunnerID = "https://github.com/actions/runner@v0.1" + +func (n *Npm) ProvenanceEnvelope() *dsse.Envelope { + return n.verifiedProvenanceAtt.Envelope +} + +func (n *Npm) ProvenanceLeafCertificate() *x509.Certificate { + return n.verifiedProvenanceAtt.SigningCert +} + +func NpmNew(ctx context.Context, root *TrustedRoot, attestationBytes []byte) (*Npm, error) { + var attestations []attestation + if err := json.Unmarshal(attestationBytes, &attestations); err != nil { + return nil, fmt.Errorf("%w: json.Unmarshal: %v", errrorInvalidAttestations, err) + } + + prov, pub, err := extractAttestations(attestations) + if err != nil { + return nil, err + } + return &Npm{ + ctx: ctx, + root: root, + provenanceAttestation: prov, + publishAttestation: pub, + }, nil +} + +func extractAttestations(attestations []attestation) (*attestation, *attestation, error) { + if len(attestations) < 2 { + return nil, nil, fmt.Errorf("%w: invalid number of attestations: %v", errrorInvalidAttestations, len(attestations)) + } + + var provenanceAttestation *attestation + var publishAttestation *attestation + for i := range attestations { + att := attestations[i] + // Provenance type verification. + if att.PredicateType == slsaprovenance.ProvenanceV02Type { + provenanceAttestation = &att + } + // Publish type verification. + if strings.HasPrefix(att.PredicateType, publishAttestationV01) { + publishAttestation = &att + } + } + + if provenanceAttestation == nil || publishAttestation == nil { + return nil, nil, fmt.Errorf("%w: invalid attestation types", errrorInvalidAttestations) + } + return provenanceAttestation, publishAttestation, nil +} + +func (n *Npm) verifyProvenanceAttestationSignature() error { + // Re-use the standard bundle verification. + signedProvenance, err := VerifyProvenanceBundle(n.ctx, n.provenanceAttestation.BundleBytes, n.root) + if err != nil { + return err + } + n.verifiedProvenanceAtt = signedProvenance + return nil +} + +func (n *Npm) verifyPublishAttesttationSignature() error { + // First verify the bundle and its rekor entry. + signedPublish, err := verifyBundleAndEntryFromBytes(n.ctx, n.publishAttestation.BundleBytes, n.root, false) + if err != nil { + return err + } + + // Second, we verify the signature, which uses a static key. + // Extract payload. + env := signedPublish.Envelope + payload, err := utils.PayloadFromEnvelope(env) + if err != nil { + return err + } + + // Extract the signature. + if len(env.Signatures) == 0 { + return fmt.Errorf("%w: no signatures found in envelope", serrors.ErrorNoValidSignature) + } + + // The registry signs with a single, static, non-rotated key. + sig := env.Signatures[0].Sig + // TODO(#496): verify the keyid, both in DSSE and hint. + + // Verify the signature. + payloadHash := sha256.Sum256(payload) + rawKey, err := base64.StdEncoding.DecodeString(npmRegistryPublicKey) + if err != nil { + return fmt.Errorf("DecodeString: %w", err) + } + + key, err := x509.ParsePKIXPublicKey(rawKey) + if err != nil { + return fmt.Errorf("x509.ParsePKIXPublicKey: %w", err) + } + + pubKey, ok := key.(*ecdsa.PublicKey) + if !ok { + return fmt.Errorf("%w: public key not of type ECDSA", err) + } + + rsig, err := utils.DecodeSignature(sig) + if err != nil { + return fmt.Errorf("decodeSigature: %w: %s", serrors.ErrorInvalidEncoding, err) + } + + if ecdsa.VerifyASN1(pubKey, payloadHash[:], rsig) { + return fmt.Errorf("%w: %s", serrors.ErrorInvalidSignature, sig) + } + + // Verification done. + n.verifiedPublishAtt = signedPublish + return nil +} + +func (n *Npm) verifyIntotoHeaders() error { + if err := verifyIntotoTypes(n.verifiedProvenanceAtt, + slsaprovenance.ProvenanceV02Type, intoto.PayloadType, false); err != nil { + return err + } + if err := verifyIntotoTypes(n.verifiedPublishAtt, + publishAttestationV01, intoto.PayloadType, true); err != nil { + return err + } + return nil +} + +func verifyIntotoTypes(att *SignedAttestation, predicateType, payloadType string, prefix bool) error { + env := att.Envelope + pyld, err := base64.StdEncoding.DecodeString(env.Payload) + if err != nil { + return fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, err.Error()) + } + + var statement intoto.Statement + if err := json.Unmarshal(pyld, &statement); err != nil { + return fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, err.Error()) + } + + // Envelope verification. + if env.PayloadType != payloadType { + return fmt.Errorf("%w: expected payload type '%v', got '%s'", + serrors.ErrorInvalidDssePayload, payloadType, env.PayloadType) + } + + // Statement verification. + if statement.Type != intoto.StatementInTotoV01 { + return fmt.Errorf("%w: expected statement type '%v', got '%s'", + serrors.ErrorInvalidDssePayload, intoto.StatementInTotoV01, 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) + } + + return nil +} + +func (n *Npm) verifiedProvenanceBytes() ([]byte, error) { + // TODO(#493): prune the provenance and return only + // verified fields. + // NOTE: we currently don't verify the materials' commit sha. + return []byte{}, nil +} + +func (n *Npm) verifyPackageName(name *string) error { + if name == nil { + return nil + } + + // Verify subject name in provenance. + if err := verifyProvenanceSubjectName(n.verifiedProvenanceAtt, *name); err != nil { + return err + } + + // Verify subject name in publish attestation. + if err := verifyPublishSubjectName(n.verifiedPublishAtt, *name); err != nil { + return err + } + + // Verify predicate name in publish attestation. + if err := verifyPublishPredicateName(n.verifiedPublishAtt, *name); err != nil { + return err + } + + return nil +} + +func (n *Npm) verifyPackageVersion(version *string) error { + if version == nil { + return nil + } + + // Verify subject version in provenance. + if err := verifyProvenanceSubjectVersion(n.verifiedProvenanceAtt, *version); err != nil { + return err + } + + // Verify subject version in publish attestation. + if err := verifyPublishSubjectVersion(n.verifiedPublishAtt, *version); err != nil { + return err + } + + // Verify predicate version in publish attestation. + if err := verifyPublishPredicateVersion(n.verifiedPublishAtt, *version); err != nil { + return err + } + + return nil +} + +func verifyPublishPredicateVersion(att *SignedAttestation, expectedVersion string) error { + _, version, err := getPublishPredicateData(att) + if err != nil { + return err + } + if version != expectedVersion { + return fmt.Errorf("%w: got '%v', expected '%v'", serrors.ErrorMismatchPackageVersion, + version, expectedVersion) + } + return nil +} + +func verifyPublishPredicateName(att *SignedAttestation, expectedName string) error { + name, _, err := getPublishPredicateData(att) + if err != nil { + return err + } + if name != expectedName { + return fmt.Errorf("%w: got '%v', expected '%v'", serrors.ErrorMismatchPackageName, + name, expectedName) + } + return nil +} + +func getPublishPredicateData(att *SignedAttestation) (string, string, error) { + env := att.Envelope + pyld, err := base64.StdEncoding.DecodeString(env.Payload) + if err != nil { + return "", "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, err.Error()) + } + + statement := struct { + intoto.StatementHeader + Predicate struct { + Version string `json:"version"` + Name string `json:"name"` + } `json:"predicate"` + }{} + if err := json.Unmarshal(pyld, &statement); err != nil { + return "", "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, err.Error()) + } + + return statement.Predicate.Name, statement.Predicate.Version, nil +} + +func verifyProvenanceSubjectVersion(att *SignedAttestation, expectedVersion string) error { + subject, err := getSubject(att) + if err != nil { + return err + } + + _, subVersion, err := getPackageNameAndVersion(subject) + if err != nil { + return err + } + + if subVersion != expectedVersion { + return fmt.Errorf("%w: got '%v', expected '%v'", serrors.ErrorMismatchPackageVersion, + subVersion, expectedVersion) + } + + return nil +} + +func verifyPublishSubjectVersion(att *SignedAttestation, expectedVersion string) error { + _, version, err := getPublishPredicateData(att) + if err != nil { + return err + } + + if version != expectedVersion { + return fmt.Errorf("%w: got '%v', expected '%v'", serrors.ErrorMismatchPackageVersion, + version, expectedVersion) + } + + return nil +} + +func verifyPublishSubjectName(att *SignedAttestation, expectedName string) error { + name, _, err := getPublishPredicateData(att) + if err != nil { + return err + } + + return verifyName(name, expectedName) +} + +func verifyProvenanceSubjectName(att *SignedAttestation, expectedName string) error { + prov, err := slsaprovenance.ProvenanceFromEnvelope(att.Envelope) + if err != nil { + return nil + } + + subjects, err := prov.Subjects() + if err != nil { + return fmt.Errorf("%w", serrors.ErrorInvalidDssePayload) + } + if len(subjects) != 1 { + return fmt.Errorf("%w: expected 1 subject, got %v", serrors.ErrorInvalidDssePayload, len(subjects)) + } + + // Package name starts with a prefix. + prefix := "pkg:npm/" + if !strings.HasPrefix(subjects[0].Name, prefix) { + return fmt.Errorf("%w: %s", serrors.ErrorInvalidPackageName, subjects[0].Name) + } + + // URL decode the package name from the attestation. + subjectName, err := url.QueryUnescape(subjects[0].Name[len(prefix):]) + if err != nil { + return fmt.Errorf("%w: %s", serrors.ErrorInvalidEncoding, err) + } + + return verifyName(subjectName, expectedName) +} + +func verifyName(actual, expected string) error { + subName, _, err := getPackageNameAndVersion(actual) + if err != nil { + return err + } + + if subName != expected { + return fmt.Errorf("%w: got '%v', expected '%v'", serrors.ErrorMismatchPackageName, + subName, expected) + } + + return nil +} + +func getPackageNameAndVersion(name string) (string, string, error) { + var pkgname, pkgtag string + n := name + if strings.HasPrefix(name, "@") { + n = n[1:] + } + parts := strings.Split(n, "@") + if len(parts) > 2 { + return "", "", fmt.Errorf("%w: %v", serrors.ErrorInvalidPackageName, name) + } + + pkgname = parts[0] + if strings.HasPrefix(name, "@") { + pkgname = "@" + pkgname + } + if len(parts) == 2 { + pkgtag = parts[1] + } + + return pkgname, pkgtag, nil +} + +func getSubject(att *SignedAttestation) (string, error) { + prov, err := slsaprovenance.ProvenanceFromEnvelope(att.Envelope) + if err != nil { + return "", err + } + + subjects, err := prov.Subjects() + if err != nil { + return "", fmt.Errorf("%w", err) + } + if len(subjects) != 1 { + return "", fmt.Errorf("%w: subject length: %v", serrors.ErrorInvalidSubject, len(subjects)) + } + + // Package name starts with a prefix. + prefix := "pkg:npm/" + if !strings.HasPrefix(subjects[0].Name, prefix) { + return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidPackageName, subjects[0].Name) + } + + // URL decode the package name from the attestation. + subject, err := url.QueryUnescape(subjects[0].Name[len(prefix):]) + if err != nil { + return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidEncoding, err) + } + return subject, err +} diff --git a/verifiers/internal/gha/npm_test.go b/verifiers/internal/gha/npm_test.go new file mode 100644 index 0000000..b9e10fb --- /dev/null +++ b/verifiers/internal/gha/npm_test.go @@ -0,0 +1,894 @@ +package gha + +import ( + "context" + "fmt" + "os" + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + + intoto "github.com/in-toto/in-toto-golang/in_toto" + dsselib "github.com/secure-systems-lab/go-securesystemslib/dsse" + serrors "github.com/slsa-framework/slsa-verifier/v2/errors" + "github.com/slsa-framework/slsa-verifier/v2/verifiers/internal/gha/slsaprovenance" +) + +func Test_verifyName(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + actual string + expected string + err error + }{ + { + name: "scoped with version same", + actual: "@laurentsimon/provenance-npm-test@1.0.0", + expected: "@laurentsimon/provenance-npm-test", + }, + { + name: "scoped no version same", + actual: "@laurentsimon/provenance-npm-test", + expected: "@laurentsimon/provenance-npm-test", + }, + { + name: "scoped with version different", + actual: "@laurentsimon/provenance-npm-test@1.0.0", + expected: "@laurentsimon/provenance-npm-tes", + err: serrors.ErrorMismatchPackageName, + }, + { + name: "scoped not same 1", + actual: "@laurentsimon/provenance-npm-test", + expected: "@aurentsimon/provenance-npm-test", + err: serrors.ErrorMismatchPackageName, + }, + { + name: "scoped not same 2", + actual: "@laurentsimon/provenance-npm-test", + expected: "@laurentsimon/provenance-npm-tes", + err: serrors.ErrorMismatchPackageName, + }, + } + for _, tt := range tests { + tt := tt // Re-initializing variable so it is not changed while executing the closure below + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + err := verifyName(tt.actual, tt.expected) + + if !errCmp(err, tt.err) { + t.Errorf(cmp.Diff(err, tt.expected)) + } + }) + } +} + +func Test_verifyPublishSubjectVersion(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + att *SignedAttestation + version string + err error + }{ + { + name: "correct version", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsCiAgICAidmVyc2lvbiI6ICIxLjAuMCIsCiAgICAicmVnaXN0cnkiOiAiaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmciCiAgfQp9Cg==", + }, + }, + version: "1.0.0", + }, + { + name: "incorrect subset version", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsCiAgICAidmVyc2lvbiI6ICIxLjAuMCIsCiAgICAicmVnaXN0cnkiOiAiaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmciCiAgfQp9Cg==", + }, + }, + version: "1.0", + err: serrors.ErrorMismatchPackageVersion, + }, + { + name: "incorrect patch version", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsCiAgICAidmVyc2lvbiI6ICIxLjAuMCIsCiAgICAicmVnaXN0cnkiOiAiaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmciCiAgfQp9Cg==", + }, + }, + version: "1.0.1", + err: serrors.ErrorMismatchPackageVersion, + }, + { + name: "incorrect minor version", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsCiAgICAidmVyc2lvbiI6ICIxLjAuMCIsCiAgICAicmVnaXN0cnkiOiAiaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmciCiAgfQp9Cg==", + }, + }, + version: "1.1.0", + err: serrors.ErrorMismatchPackageVersion, + }, + { + name: "incorrect major version", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsCiAgICAidmVyc2lvbiI6ICIxLjAuMCIsCiAgICAicmVnaXN0cnkiOiAiaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmciCiAgfQp9Cg==", + }, + }, + version: "2.0.0", + err: serrors.ErrorMismatchPackageVersion, + }, + } + for _, tt := range tests { + tt := tt // Re-initializing variable so it is not changed while executing the closure below + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + err := verifyPublishSubjectVersion(tt.att, tt.version) + + if !errCmp(err, tt.err) { + t.Errorf(cmp.Diff(err, tt.err)) + } + }) + } +} + +func Test_verifyProvenanceSubjectVersion(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + att *SignedAttestation + version string + err error + }{ + { + name: "correct version", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogWwogICAgewogICAgICAibmFtZSI6ICJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhNTEyIjogIjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIgogICAgICB9CiAgICB9CiAgXSwKICAicHJlZGljYXRlVHlwZSI6ICJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjAuMiIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJidWlsZFR5cGUiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGkvZ2hhQHYxIiwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGlAOS41LjAiCiAgICB9CiAgfQp9Cg==", + }, + }, + version: "1.0.0", + }, + { + name: "incorrect subset version", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogWwogICAgewogICAgICAibmFtZSI6ICJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhNTEyIjogIjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIgogICAgICB9CiAgICB9CiAgXSwKICAicHJlZGljYXRlVHlwZSI6ICJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjAuMiIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJidWlsZFR5cGUiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGkvZ2hhQHYxIiwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGlAOS41LjAiCiAgICB9CiAgfQp9Cg==", + }, + }, + version: "1.0", + err: serrors.ErrorMismatchPackageVersion, + }, + { + name: "incorrect patch version", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogWwogICAgewogICAgICAibmFtZSI6ICJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhNTEyIjogIjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIgogICAgICB9CiAgICB9CiAgXSwKICAicHJlZGljYXRlVHlwZSI6ICJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjAuMiIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJidWlsZFR5cGUiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGkvZ2hhQHYxIiwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGlAOS41LjAiCiAgICB9CiAgfQp9Cg==", + }, + }, + version: "1.0.1", + err: serrors.ErrorMismatchPackageVersion, + }, + { + name: "incorrect minor version", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogWwogICAgewogICAgICAibmFtZSI6ICJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhNTEyIjogIjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIgogICAgICB9CiAgICB9CiAgXSwKICAicHJlZGljYXRlVHlwZSI6ICJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjAuMiIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJidWlsZFR5cGUiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGkvZ2hhQHYxIiwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGlAOS41LjAiCiAgICB9CiAgfQp9Cg==", + }, + }, + version: "1.1.0", + err: serrors.ErrorMismatchPackageVersion, + }, + { + name: "incorrect major version", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogWwogICAgewogICAgICAibmFtZSI6ICJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhNTEyIjogIjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIgogICAgICB9CiAgICB9CiAgXSwKICAicHJlZGljYXRlVHlwZSI6ICJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjAuMiIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJidWlsZFR5cGUiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGkvZ2hhQHYxIiwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGlAOS41LjAiCiAgICB9CiAgfQp9Cg==", + }, + }, + version: "2.0.0", + err: serrors.ErrorMismatchPackageVersion, + }, + } + for _, tt := range tests { + tt := tt // Re-initializing variable so it is not changed while executing the closure below + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + err := verifyProvenanceSubjectVersion(tt.att, tt.version) + + if !errCmp(err, tt.err) { + t.Errorf(cmp.Diff(err, tt.err)) + } + }) + } +} + +func Test_verifyPublishSubjectName(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + att *SignedAttestation + subject string + err error + }{ + { + name: "correct name", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsCiAgICAidmVyc2lvbiI6ICIxLjAuMCIsCiAgICAicmVnaXN0cnkiOiAiaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmciCiAgfQp9Cg==", + }, + }, + subject: "@laurentsimon/provenance-npm-test", + }, + { + name: "incorrect name", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsCiAgICAidmVyc2lvbiI6ICIxLjAuMCIsCiAgICAicmVnaXN0cnkiOiAiaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmciCiAgfQp9Cg==", + }, + }, + subject: "wrong name", + err: serrors.ErrorMismatchPackageName, + }, + { + name: "incorrect scope", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsCiAgICAidmVyc2lvbiI6ICIxLjAuMCIsCiAgICAicmVnaXN0cnkiOiAiaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmciCiAgfQp9Cg==", + }, + }, + subject: "laurentsimon/provenance-npm-test", + err: serrors.ErrorMismatchPackageName, + }, + { + name: "incorrect with version", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsCiAgICAidmVyc2lvbiI6ICIxLjAuMCIsCiAgICAicmVnaXN0cnkiOiAiaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmciCiAgfQp9Cg==", + }, + }, + subject: "@laurentsimon/provenance-npm-test@1.0.0", + err: serrors.ErrorMismatchPackageName, + }, + } + for _, tt := range tests { + tt := tt // Re-initializing variable so it is not changed while executing the closure below + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + err := verifyPublishSubjectName(tt.att, tt.subject) + + if !errCmp(err, tt.err) { + t.Errorf(cmp.Diff(err, tt.err)) + } + }) + } +} + +func Test_verifyPublishPredicateName(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + att *SignedAttestation + subject string + err error + }{ + { + name: "correct name", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdC1wcmVkIiwKICAgICJ2ZXJzaW9uIjogIjEuMC4wIiwKICAgICJyZWdpc3RyeSI6ICJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyIKICB9Cn0K", + }, + }, + subject: "@laurentsimon/provenance-npm-test-pred", + }, + { + name: "incorrect name", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdC1wcmVkIiwKICAgICJ2ZXJzaW9uIjogIjEuMC4wIiwKICAgICJyZWdpc3RyeSI6ICJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyIKICB9Cn0K", + }, + }, + subject: "wrong name", + err: serrors.ErrorMismatchPackageName, + }, + { + name: "incorrect scope", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdC1wcmVkIiwKICAgICJ2ZXJzaW9uIjogIjEuMC4wIiwKICAgICJyZWdpc3RyeSI6ICJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyIKICB9Cn0K", + }, + }, + subject: "laurentsimon/provenance-npm-test-pred", + err: serrors.ErrorMismatchPackageName, + }, + { + name: "incorrect with version", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdC1wcmVkIiwKICAgICJ2ZXJzaW9uIjogIjEuMC4wIiwKICAgICJyZWdpc3RyeSI6ICJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyIKICB9Cn0K", + }, + }, + subject: "@laurentsimon/provenance-npm-test-pred@1.0.0", + err: serrors.ErrorMismatchPackageName, + }, + } + for _, tt := range tests { + tt := tt // Re-initializing variable so it is not changed while executing the closure below + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + err := verifyPublishPredicateName(tt.att, tt.subject) + + if !errCmp(err, tt.err) { + t.Errorf(cmp.Diff(err, tt.err)) + } + }) + } +} + +func Test_verifyPublishPredicateVersion(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + att *SignedAttestation + version string + err error + }{ + { + name: "correct version", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdC1wcmVkIiwKICAgICJ2ZXJzaW9uIjogIjEuMC4wIiwKICAgICJyZWdpc3RyeSI6ICJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyIKICB9Cn0K", + }, + }, + version: "1.0.0", + }, + { + name: "incorrect subset version", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdC1wcmVkIiwKICAgICJ2ZXJzaW9uIjogIjEuMC4wIiwKICAgICJyZWdpc3RyeSI6ICJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyIKICB9Cn0K", + }, + }, + version: "1.0", + err: serrors.ErrorMismatchPackageVersion, + }, + { + name: "incorrect patch version", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdC1wcmVkIiwKICAgICJ2ZXJzaW9uIjogIjEuMC4wIiwKICAgICJyZWdpc3RyeSI6ICJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyIKICB9Cn0K", + }, + }, + version: "1.0.1", + err: serrors.ErrorMismatchPackageVersion, + }, + { + name: "incorrect minor version", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdC1wcmVkIiwKICAgICJ2ZXJzaW9uIjogIjEuMC4wIiwKICAgICJyZWdpc3RyeSI6ICJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyIKICB9Cn0K", + }, + }, + version: "1.1.0", + err: serrors.ErrorMismatchPackageVersion, + }, + { + name: "incorrect major version", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdC1wcmVkIiwKICAgICJ2ZXJzaW9uIjogIjEuMC4wIiwKICAgICJyZWdpc3RyeSI6ICJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyIKICB9Cn0K", + }, + }, + version: "2.0.0", + err: serrors.ErrorMismatchPackageVersion, + }, + } + for _, tt := range tests { + tt := tt // Re-initializing variable so it is not changed while executing the closure below + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + err := verifyPublishPredicateVersion(tt.att, tt.version) + + if !errCmp(err, tt.err) { + t.Errorf(cmp.Diff(err, tt.err)) + } + }) + } +} + +func Test_verifyProvenanceSubjectName(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + att *SignedAttestation + subject string + err error + }{ + { + name: "correct name", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogWwogICAgewogICAgICAibmFtZSI6ICJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhNTEyIjogIjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIgogICAgICB9CiAgICB9CiAgXSwKICAicHJlZGljYXRlVHlwZSI6ICJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjAuMiIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJidWlsZFR5cGUiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGkvZ2hhQHYxIiwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGlAOS41LjAiCiAgICB9CiAgfQp9Cg==", + }, + }, + subject: "@laurentsimon/provenance-npm-test", + }, + { + name: "incorrect name", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogWwogICAgewogICAgICAibmFtZSI6ICJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhNTEyIjogIjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIgogICAgICB9CiAgICB9CiAgXSwKICAicHJlZGljYXRlVHlwZSI6ICJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjAuMiIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJidWlsZFR5cGUiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGkvZ2hhQHYxIiwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGlAOS41LjAiCiAgICB9CiAgfQp9Cg==", + }, + }, + subject: "wrong name", + err: serrors.ErrorMismatchPackageName, + }, + { + name: "incorrect scope", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogWwogICAgewogICAgICAibmFtZSI6ICJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhNTEyIjogIjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIgogICAgICB9CiAgICB9CiAgXSwKICAicHJlZGljYXRlVHlwZSI6ICJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjAuMiIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJidWlsZFR5cGUiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGkvZ2hhQHYxIiwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGlAOS41LjAiCiAgICB9CiAgfQp9Cg==", + }, + }, + subject: "laurentsimon/provenance-npm-test", + err: serrors.ErrorMismatchPackageName, + }, + { + name: "incorrect with version", + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogWwogICAgewogICAgICAibmFtZSI6ICJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhNTEyIjogIjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIgogICAgICB9CiAgICB9CiAgXSwKICAicHJlZGljYXRlVHlwZSI6ICJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjAuMiIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJidWlsZFR5cGUiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGkvZ2hhQHYxIiwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGlAOS41LjAiCiAgICB9CiAgfQp9Cg==", + }, + }, + subject: "@laurentsimon/provenance-npm-test@1.0.0", + err: serrors.ErrorMismatchPackageName, + }, + } + for _, tt := range tests { + tt := tt // Re-initializing variable so it is not changed while executing the closure below + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + err := verifyProvenanceSubjectName(tt.att, tt.subject) + + if !errCmp(err, tt.err) { + t.Errorf(cmp.Diff(err, tt.err)) + } + }) + } +} + +func Test_verifyPackageName(t *testing.T) { + t.Parallel() + ctx := context.Background() + + trustedRoot, err := GetTrustedRoot(ctx) + if err != nil { + t.Fatal(err) + } + + tests := []struct { + name string + path string + subject string + err error + }{ + { + name: "correct name", + path: "npm-attestations.intoto.sigstore", + subject: "@laurentsimon/provenance-npm-test", + }, + { + name: "incorrect name", + path: "npm-attestations.intoto.sigstore", + subject: "wrong name", + err: serrors.ErrorMismatchPackageName, + }, + { + name: "incorrect scope", + path: "npm-attestations.intoto.sigstore", + subject: "laurentsimon/provenance-npm-test", + err: serrors.ErrorMismatchPackageName, + }, + { + name: "incorrect with version", + path: "npm-attestations.intoto.sigstore", + subject: "@laurentsimon/provenance-npm-test@1.0.0", + err: serrors.ErrorMismatchPackageName, + }, + } + for _, tt := range tests { + tt := tt // Re-initializing variable so it is not changed while executing the closure below + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + content, err := os.ReadFile(filepath.Join("testdata", tt.path)) + if err != nil { + panic(fmt.Errorf("os.ReadFile: %w", err)) + } + + npm, err := NpmNew(ctx, trustedRoot, content) + if err != nil { + panic(fmt.Errorf("NpmNew: %w", err)) + } + // Set provenance attestation. + env, err := getEnvelopeFromBundleBytes(npm.provenanceAttestation.BundleBytes) + if err != nil { + panic(fmt.Errorf("getEnvelopeFromBundleBytes: %w", err)) + } + npm.verifiedProvenanceAtt = &SignedAttestation{ + Envelope: env, + } + + env, err = getEnvelopeFromBundleBytes(npm.publishAttestation.BundleBytes) + if err != nil { + panic(fmt.Errorf("getEnvelopeFromBundleBytes: %w", err)) + } + npm.verifiedPublishAtt = &SignedAttestation{ + Envelope: env, + } + + err = npm.verifyPackageName(&tt.subject) + if !errCmp(err, tt.err) { + t.Errorf(cmp.Diff(err, tt.err)) + } + }) + } +} + +func Test_verifyPackageVersion(t *testing.T) { + t.Parallel() + ctx := context.Background() + + trustedRoot, err := GetTrustedRoot(ctx) + if err != nil { + t.Fatal(err) + } + + tests := []struct { + name string + path string + version string + err error + }{ + { + name: "correct name", + path: "npm-attestations.intoto.sigstore", + version: "1.0.0", + }, + { + name: "incorrect patch", + path: "npm-attestations.intoto.sigstore", + version: "1.0.1", + err: serrors.ErrorMismatchPackageVersion, + }, + { + name: "incorrect minor", + path: "npm-attestations.intoto.sigstore", + version: "1.1.0", + err: serrors.ErrorMismatchPackageVersion, + }, + { + name: "incorrect major", + path: "npm-attestations.intoto.sigstore", + version: "2.0.0", + err: serrors.ErrorMismatchPackageVersion, + }, + } + for _, tt := range tests { + tt := tt // Re-initializing variable so it is not changed while executing the closure below + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + content, err := os.ReadFile(filepath.Join("testdata", tt.path)) + if err != nil { + panic(fmt.Errorf("os.ReadFile: %w", err)) + } + + npm, err := NpmNew(ctx, trustedRoot, content) + if err != nil { + panic(fmt.Errorf("NpmNew: %w", err)) + } + // Set provenance attestation. + env, err := getEnvelopeFromBundleBytes(npm.provenanceAttestation.BundleBytes) + if err != nil { + panic(fmt.Errorf("getEnvelopeFromBundleBytes: %w", err)) + } + npm.verifiedProvenanceAtt = &SignedAttestation{ + Envelope: env, + } + + env, err = getEnvelopeFromBundleBytes(npm.publishAttestation.BundleBytes) + if err != nil { + panic(fmt.Errorf("getEnvelopeFromBundleBytes: %w", err)) + } + npm.verifiedPublishAtt = &SignedAttestation{ + Envelope: env, + } + + err = npm.verifyPackageVersion(&tt.version) + if !errCmp(err, tt.err) { + t.Errorf(cmp.Diff(err, tt.err)) + } + }) + } +} + +func Test_verifyIntotoTypes(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + att *SignedAttestation + predicateType string + payloadType string + prefix bool + err error + }{ + { + name: "prov correct", + predicateType: slsaprovenance.ProvenanceV02Type, + payloadType: intoto.PayloadType, + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogWwogICAgewogICAgICAibmFtZSI6ICJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhNTEyIjogIjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIgogICAgICB9CiAgICB9CiAgXSwKICAicHJlZGljYXRlVHlwZSI6ICJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjAuMiIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJidWlsZFR5cGUiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGkvZ2hhQHYxIiwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGlAOS41LjAiCiAgICB9CiAgfQp9Cg==", + }, + }, + }, + { + name: "prov mismatch payload type", + predicateType: slsaprovenance.ProvenanceV02Type, + payloadType: intoto.PayloadType, + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+jso", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogWwogICAgewogICAgICAibmFtZSI6ICJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhNTEyIjogIjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIgogICAgICB9CiAgICB9CiAgXSwKICAicHJlZGljYXRlVHlwZSI6ICJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjAuMiIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJidWlsZFR5cGUiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGkvZ2hhQHYxIiwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGlAOS41LjAiCiAgICB9CiAgfQp9Cg==", + }, + }, + err: serrors.ErrorInvalidDssePayload, + }, + { + name: "prov mismatch predicate type", + predicateType: slsaprovenance.ProvenanceV02Type + "a", + payloadType: intoto.PayloadType, + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogWwogICAgewogICAgICAibmFtZSI6ICJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhNTEyIjogIjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIgogICAgICB9CiAgICB9CiAgXSwKICAicHJlZGljYXRlVHlwZSI6ICJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjAuMiIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJidWlsZFR5cGUiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGkvZ2hhQHYxIiwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9jbGlAOS41LjAiCiAgICB9CiAgfQp9Cg==", + }, + }, + err: serrors.ErrorInvalidDssePayload, + }, + { + name: "publish correct", + predicateType: publishAttestationV01, + prefix: true, + payloadType: intoto.PayloadType, + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdC1wcmVkIiwKICAgICJ2ZXJzaW9uIjogIjEuMC4wIiwKICAgICJyZWdpc3RyeSI6ICJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyIKICB9Cn0K", + }, + }, + }, + { + name: "publish mismatch payload type", + predicateType: publishAttestationV01, + prefix: true, + payloadType: intoto.PayloadType, + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+jso", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdC1wcmVkIiwKICAgICJ2ZXJzaW9uIjogIjEuMC4wIiwKICAgICJyZWdpc3RyeSI6ICJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyIKICB9Cn0K", + }, + }, + err: serrors.ErrorInvalidDssePayload, + }, + { + name: "publish mismatch predicate type", + predicateType: publishAttestationV01 + "a", + prefix: true, + payloadType: intoto.PayloadType, + att: &SignedAttestation{ + Envelope: &dsselib.Envelope{ + PayloadType: "application/vnd.in-toto+json", + Payload: "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdC1wcmVkIiwKICAgICJ2ZXJzaW9uIjogIjEuMC4wIiwKICAgICJyZWdpc3RyeSI6ICJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyIKICB9Cn0K", + }, + }, + err: serrors.ErrorInvalidDssePayload, + }, + } + for _, tt := range tests { + tt := tt // Re-initializing variable so it is not changed while executing the closure below + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + err := verifyIntotoTypes(tt.att, tt.predicateType, tt.payloadType, tt.prefix) + if !errCmp(err, tt.err) { + t.Errorf(cmp.Diff(err, tt.err)) + } + }) + } +} + +func Test_verifyIntotoHeaders(t *testing.T) { + t.Parallel() + ctx := context.Background() + + trustedRoot, err := GetTrustedRoot(ctx) + if err != nil { + t.Fatal(err) + } + + tests := []struct { + name string + path string + version string + err error + }{ + { + name: "correct", + path: "npm-attestations.intoto.sigstore", + }, + { + name: "prov incorrect stmt predicate type", + path: "npm-stmt-mismatch-prov-predicatetype.intoto.sigstore", + err: serrors.ErrorInvalidDssePayload, + }, + { + name: "prov incorrect stmt type", + path: "npm-stmt-mismatch-prov-type.intoto.sigstore", + err: serrors.ErrorInvalidDssePayload, + }, + { + name: "prov incorrect att payload type", + path: "npm-att-mismatch-prov-payloadtype.intoto.sigstore", + err: serrors.ErrorInvalidDssePayload, + }, + { + name: "pub incorrect stmt predicate type", + path: "npm-stmt-mismatch-pub-predicatetype.intoto.sigstore", + err: serrors.ErrorInvalidDssePayload, + }, + { + name: "pub incorrect att payload type", + path: "npm-att-mismatch-pub-payloadtype.intoto.sigstore", + err: serrors.ErrorInvalidDssePayload, + }, + { + name: "pub incorrect stmt type", + path: "npm-stmt-mismatch-pub-type.intoto.sigstore", + err: serrors.ErrorInvalidDssePayload, + }, + } + for _, tt := range tests { + tt := tt // Re-initializing variable so it is not changed while executing the closure below + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + content, err := os.ReadFile(filepath.Join("testdata", tt.path)) + if err != nil { + panic(fmt.Errorf("os.ReadFile: %w", err)) + } + + npm, err := NpmNew(ctx, trustedRoot, content) + if err != nil { + panic(fmt.Errorf("NpmNew: %w", err)) + } + // Set provenance attestation. + env, err := getEnvelopeFromBundleBytes(npm.provenanceAttestation.BundleBytes) + if err != nil { + panic(fmt.Errorf("getEnvelopeFromBundleBytes: %w", err)) + } + npm.verifiedProvenanceAtt = &SignedAttestation{ + Envelope: env, + } + + env, err = getEnvelopeFromBundleBytes(npm.publishAttestation.BundleBytes) + if err != nil { + panic(fmt.Errorf("getEnvelopeFromBundleBytes: %w", err)) + } + npm.verifiedPublishAtt = &SignedAttestation{ + Envelope: env, + } + + err = npm.verifyIntotoHeaders() + if !errCmp(err, tt.err) { + t.Errorf(cmp.Diff(err, tt.err)) + } + }) + } +} + +func Test_NpmNew(t *testing.T) { + t.Parallel() + ctx := context.Background() + + trustedRoot, err := GetTrustedRoot(ctx) + if err != nil { + t.Fatal(err) + } + + tests := []struct { + name string + path string + version string + err error + }{ + { + name: "correct", + path: "npm-attestations.intoto.sigstore", + }, + { + name: "prov incorrect att predicate type", + path: "npm-att-mismatch-prov-predicatetype.intoto.sigstore", + err: errrorInvalidAttestations, + }, + { + name: "publish incorrect att predicate type", + path: "npm-att-mismatch-pub-predicatetype.intoto.sigstore", + err: errrorInvalidAttestations, + }, + } + for _, tt := range tests { + tt := tt // Re-initializing variable so it is not changed while executing the closure below + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + content, err := os.ReadFile(filepath.Join("testdata", tt.path)) + if err != nil { + panic(fmt.Errorf("os.ReadFile: %w", err)) + } + + _, err = NpmNew(ctx, trustedRoot, content) + if !errCmp(err, tt.err) { + t.Errorf(cmp.Diff(err, tt.err)) + } + }) + } +} diff --git a/verifiers/internal/gha/provenance.go b/verifiers/internal/gha/provenance.go index 7aa8c43..e4585e9 100644 --- a/verifiers/internal/gha/provenance.go +++ b/verifiers/internal/gha/provenance.go @@ -71,7 +71,7 @@ func asURI(s string) string { } // Verify source URI in provenance statement. -func verifySourceURI(prov slsaprovenance.Provenance, expectedSourceURI string) error { +func verifySourceURI(prov slsaprovenance.Provenance, expectedSourceURI string, verifyMaterials bool) error { source := asURI(expectedSourceURI) // We expect github.com URIs only. @@ -95,6 +95,10 @@ func verifySourceURI(prov slsaprovenance.Provenance, expectedSourceURI string) e } // Verify source from material section. + // TODO(#492): disable this option. + if !verifyMaterials { + return nil + } materialSourceURI, err := prov.SourceURI() if err != nil { return err @@ -136,18 +140,20 @@ func sourceFromURI(uri string) (string, error) { return r[0], nil } -// Verify SHA256 Subject Digest from the provenance statement. -func verifySha256Digest(prov slsaprovenance.Provenance, expectedHash string) error { +// Verify Subject Digest from the provenance statement. +func verifyDigest(prov slsaprovenance.Provenance, expectedHash string) error { subjects, err := prov.Subjects() if err != nil { return err } + // 8 bit represented in hex, so 8/2=4. + l := len(expectedHash) * 4 for _, subject := range subjects { digestSet := subject.Digest - hash, exists := digestSet["sha256"] + hash, exists := digestSet[fmt.Sprintf("sha%v", l)] if !exists { - return fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "no sha256 subject digest") + return fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, fmt.Sprintf("no sha%v subject digest", l)) } if hash == expectedHash { @@ -163,7 +169,8 @@ func verifySha256Digest(prov slsaprovenance.Provenance, expectedHash string) err func VerifyProvenanceSignature(ctx context.Context, trustedRoot *TrustedRoot, rClient *client.Rekor, provenance []byte, artifactHash string) ( - *SignedAttestation, error) { + *SignedAttestation, error, +) { // Collect trusted root material for verification (Rekor pubkeys, SCT pubkeys, // Fulcio root certificates). _, err := GetTrustedRoot(ctx) @@ -186,7 +193,35 @@ func VerifyProvenanceSignature(ctx context.Context, trustedRoot *TrustedRoot, provenance, rClient, trustedRoot) } -func VerifyProvenance(env *dsselib.Envelope, provenanceOpts *options.ProvenanceOpts) error { +func VerifyNpmPackageProvenance(env *dsselib.Envelope, provenanceOpts *options.ProvenanceOpts, +) error { + prov, err := slsaprovenance.ProvenanceFromEnvelope(env) + if err != nil { + return err + } + + // Untrusted builder. + if provenanceOpts.ExpectedBuilderID == "" { + // Verify it's the npm CLI. + builderID, err := prov.BuilderID() + if err != nil { + return err + } + // TODO(#494): update the builder ID string. + if !strings.HasPrefix(builderID, "https://github.com/npm/cli@") { + return fmt.Errorf("%w: expected 'https://github.com/npm/cli' in builder.id, got '%s'", + serrors.ErrorMismatchBuilderID, builderID) + } + } else if err := verifyBuilderIDExactMatch(prov, provenanceOpts.ExpectedBuilderID); err != nil { + return err + } + // NOTE: for the non trusted builders, the information may be forgeable. + // Also, the GitHub context is not recorded for the default builder. + return VerifyProvenanceCommonOptions(prov, provenanceOpts, false) +} + +func VerifyProvenance(env *dsselib.Envelope, provenanceOpts *options.ProvenanceOpts, +) error { prov, err := slsaprovenance.ProvenanceFromEnvelope(env) if err != nil { return err @@ -199,13 +234,19 @@ func VerifyProvenance(env *dsselib.Envelope, provenanceOpts *options.ProvenanceO return err } + return VerifyProvenanceCommonOptions(prov, provenanceOpts, true) +} + +func VerifyProvenanceCommonOptions(prov slsaprovenance.Provenance, provenanceOpts *options.ProvenanceOpts, + verifyMaterials bool, +) error { // Verify source. - if err := verifySourceURI(prov, provenanceOpts.ExpectedSourceURI); err != nil { + if err := verifySourceURI(prov, provenanceOpts.ExpectedSourceURI, verifyMaterials); err != nil { return err } // Verify subject digest. - if err := verifySha256Digest(prov, provenanceOpts.ExpectedDigest); err != nil { + if err := verifyDigest(prov, provenanceOpts.ExpectedDigest); err != nil { return err } diff --git a/verifiers/internal/gha/provenance_test.go b/verifiers/internal/gha/provenance_test.go index 999355e..6057faa 100644 --- a/verifiers/internal/gha/provenance_test.go +++ b/verifiers/internal/gha/provenance_test.go @@ -26,7 +26,7 @@ func provenanceFromBytes(payload []byte) (slsaprovenance.Provenance, error) { return slsaprovenance.ProvenanceFromEnvelope(env) } -func Test_VerifySha256Subject(t *testing.T) { +func Test_VerifyDigest(t *testing.T) { t.Parallel() tests := []struct { name string @@ -149,7 +149,7 @@ func Test_VerifySha256Subject(t *testing.T) { panic(fmt.Errorf("provenanceFromBytes: %w", err)) } - err = verifySha256Digest(prov, tt.artifactHash) + err = verifyDigest(prov, tt.artifactHash) if !errCmp(err, tt.expected) { t.Errorf(cmp.Diff(err, tt.expected)) } @@ -412,7 +412,7 @@ func Test_verifySourceURI(t *testing.T) { ProvenanceStatement: tt.prov, } - err := verifySourceURI(prov02, tt.sourceURI) + err := verifySourceURI(prov02, tt.sourceURI, true) if !errCmp(err, tt.expected) { t.Errorf(cmp.Diff(err, tt.expected)) } @@ -433,7 +433,7 @@ func Test_verifySourceURI(t *testing.T) { }, }, } - err = verifySourceURI(prov1, tt.sourceURI) + err = verifySourceURI(prov1, tt.sourceURI, true) if !errCmp(err, tt.expected) { t.Errorf(cmp.Diff(err, tt.expected)) } diff --git a/verifiers/internal/gha/rekor.go b/verifiers/internal/gha/rekor.go index a356245..651f103 100644 --- a/verifiers/internal/gha/rekor.go +++ b/verifiers/internal/gha/rekor.go @@ -40,7 +40,8 @@ const ( func verifyTlogEntryByUUID(ctx context.Context, rekorClient *client.Rekor, entryUUID string, trustedRoot *TrustedRoot) ( - *models.LogEntryAnon, error) { + *models.LogEntryAnon, error, +) { params := entries.NewGetLogEntryByUUIDParamsWithContext(ctx) params.EntryUUID = entryUUID @@ -79,7 +80,8 @@ func verifyTlogEntryByUUID(ctx context.Context, rekorClient *client.Rekor, // is true, the inclusion proof along with the signed tree head. func verifyTlogEntry(ctx context.Context, e models.LogEntryAnon, verifyInclusion bool, rekorKeys *cosign.TrustedTransparencyLogPubKeys) ( - *models.LogEntryAnon, error) { + *models.LogEntryAnon, error, +) { // Verify the root hash against the current Signed Entry Tree Head verifier, err := signature.LoadECDSAVerifier(rekorKeys.Keys[*e.LogID].PubKey.(*ecdsa.PublicKey), crypto.SHA256) @@ -183,7 +185,8 @@ func getUUIDsByArtifactDigest(rClient *client.Rekor, artifactHash string) ([]str // the full intoto attestation. // The attestation generated by the slsa-github-generator libraries contain a signing certificate. func GetValidSignedAttestationWithCert(rClient *client.Rekor, - provenance []byte, trustedRoot *TrustedRoot) (*SignedAttestation, error) { + provenance []byte, trustedRoot *TrustedRoot, +) (*SignedAttestation, error) { // Use intoto attestation to find rekor entry UUIDs. params := entries.NewSearchLogQueryParams() searchLogQuery := models.SearchLogQuery{} @@ -253,7 +256,8 @@ func GetValidSignedAttestationWithCert(rClient *client.Rekor, // SearchValidSignedAttestation searches for a valid signing certificate using the Rekor // Redis search index by using the artifact digest. func SearchValidSignedAttestation(ctx context.Context, artifactHash string, provenance []byte, - rClient *client.Rekor, trustedRoot *TrustedRoot) (*SignedAttestation, error) { + rClient *client.Rekor, trustedRoot *TrustedRoot, +) (*SignedAttestation, error) { // Get Rekor UUIDs by artifact digest. uuids, err := getUUIDsByArtifactDigest(rClient, artifactHash) if err != nil { diff --git a/verifiers/internal/gha/slsaprovenance/slsaprovenance.go b/verifiers/internal/gha/slsaprovenance/slsaprovenance.go index f7a3db9..9403790 100644 --- a/verifiers/internal/gha/slsaprovenance/slsaprovenance.go +++ b/verifiers/internal/gha/slsaprovenance/slsaprovenance.go @@ -65,7 +65,7 @@ func ProvenanceFromEnvelope(env *dsselib.Envelope) (Provenance, error) { // Load the appropriate structure and unmarshal. ptype, ok := ProvenanceMap.Load(pred.PredicateType) if !ok { - return nil, fmt.Errorf("%w: %s %s", serrors.ErrorInvalidDssePayload, "unexpected predicate type ", pred.PredicateType) + return nil, fmt.Errorf("%w: unexpected predicate type '%s'", serrors.ErrorInvalidDssePayload, pred.PredicateType) } prov := ptype.(func() Provenance)() diff --git a/verifiers/internal/gha/testdata/npm-att-mismatch-prov-payloadtype.intoto.sigstore b/verifiers/internal/gha/testdata/npm-att-mismatch-prov-payloadtype.intoto.sigstore new file mode 100644 index 0000000..617235b --- /dev/null +++ b/verifiers/internal/gha/testdata/npm-att-mismatch-prov-payloadtype.intoto.sigstore @@ -0,0 +1,92 @@ +[ + { + "predicateType": "https://slsa.dev/provenance/v0.2", + "bundle": { + "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.1", + "verificationMaterial": { + "x509CertificateChain": { + "certificates": [ + { + "rawBytes": "MIIDzTCCA1SgAwIBAgIUSUNeEjOTOlxw2mAmVuog6waz+NcwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjMwMjE1MTkzMzMyWhcNMjMwMjE1MTk0MzMyWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVWrN2Ayc3U80RBnqrFssCXrFETeyMskQhLAXaOAbaPylLa6GiuhrZUEd+i2Q+kvtlOJN6WvJaoIirGUUw84scKOCAnMwggJvMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUgYNyCZHUpkzBfqlfSh2+dV/nqg8wHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wbwYDVR0RAQH/BGUwY4ZhaHR0cHM6Ly9naXRodWIuY29tL2xhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbjA5BgorBgEEAYO/MAEBBCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMB8GCisGAQQBg78wAQIEEXdvcmtmbG93X2Rpc3BhdGNoMDYGCisGAQQBg78wAQMEKDE2YmFiZmZiOTE1MzgxMWUxOTNjMDE5OTM5MzkxMzU3MzcyYjI1Y2UwJgYKKwYBBAGDvzABBAQYUHVibGlzaCBQYWNrYWdlIHRvIG5wbWpzMC4GCisGAQQBg78wAQUEIGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0MB0GCisGAQQBg78wAQYED3JlZnMvaGVhZHMvbWFpbjCBiwYKKwYBBAHWeQIEAgR9BHsAeQB3AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABhlaRXNMAAAQDAEgwRgIhAOZYHC2AyB4Mm5uV6etiegcdoB5t/3Q6e8pah2BH60urAiEAv9rv6WNIyPfXrP1yzykQldw9iExSBh/brNNjTLzP+wYwCgYIKoZIzj0EAwMDZwAwZAIwT+nOUcGmT+K1gtU/ETiJewRTXtX5bjFh0AEDWzVFlLQKk+CMCr+CmhJgfobd83qwAjAz9Wp4/krIgy+qD7oeCwlUH74MNgWpy2QU5Ox3J61wP2/0O7bhH5fDaGtYUFKZzwA=" + }, + { + "rawBytes": "MIICGjCCAaGgAwIBAgIUALnViVfnU0brJasmRkHrn/UnfaQwCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMjA0MTMyMDA2MTVaFw0zMTEwMDUxMzU2NThaMDcxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEeMBwGA1UEAxMVc2lnc3RvcmUtaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8RVS/ysH+NOvuDZyPIZtilgUF9NlarYpAd9HP1vBBH1U5CV77LSS7s0ZiH4nE7Hv7ptS6LvvR/STk798LVgMzLlJ4HeIfF3tHSaexLcYpSASr1kS0N/RgBJz/9jWCiXno3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU39Ppz1YkEZb5qNjpKFWixi4YZD8wHwYDVR0jBBgwFoAUWMAeX5FFpWapesyQoZMi0CrFxfowCgYIKoZIzj0EAwMDZwAwZAIwPCsQK4DYiZYDPIaDi5HFKnfxXx6ASSVmERfsynYBiX2X6SJRnZU84/9DZdnFvvxmAjBOt6QpBlc4J/0DxvkTCqpclvziL6BCCPnjdlIB3Pu3BxsPmygUY7Ii2zbdCdliiow=" + }, + { + "rawBytes": "MIIB9zCCAXygAwIBAgIUALZNAPFdxHPwjeDloDwyYChAO/4wCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMTEwMDcxMzU2NTlaFw0zMTEwMDUxMzU2NThaMCoxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjERMA8GA1UEAxMIc2lnc3RvcmUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT7XeFT4rb3PQGwS4IajtLk3/OlnpgangaBclYpsYBr5i+4ynB07ceb3LP0OIOZdxexX69c5iVuyJRQ+Hz05yi+UF3uBWAlHpiS5sh0+H2GHE7SXrk1EC5m1Tr19L9gg92jYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRYwB5fkUWlZql6zJChkyLQKsXF+jAfBgNVHSMEGDAWgBRYwB5fkUWlZql6zJChkyLQKsXF+jAKBggqhkjOPQQDAwNpADBmAjEAj1nHeXZp+13NWBNa+EDsDP8G1WWg1tCMWP/WHPqpaVo0jhsweNFZgSs0eE7wYI4qAjEA2WB9ot98sIkoF3vZYdd3/VtWB5b9TNMea7Ix/stJ5TfcLLeABLE4BNJOsQ4vnBHJ" + } + ] + }, + "tlogEntries": [ + { + "logIndex": "13420286", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "intoto", + "version": "0.0.2" + }, + "integratedTime": "1676489612", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCIG/LjJ5tqTgKvbA0F+96CJHIk2X0S+9cBz1Z04BfU7dLAiEA7cpf1Agv0VyEu0wR41nEZ9AZ6GVaYR5rf4AAYIZr4hk=" + }, + "inclusionProof": null, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7InB1YmxpY0tleSI6IkxTMHRMUzFDUlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVI2VkVORFFURlRaMEYzU1VKQlowbFZVMVZPWlVWcVQxUlBiSGgzTW0xQmJWWjFiMmMyZDJGNkswNWpkME5uV1VsTGIxcEplbW93UlVGM1RYY0tUbnBGVmsxQ1RVZEJNVlZGUTJoTlRXTXliRzVqTTFKMlkyMVZkVnBIVmpKTlVqUjNTRUZaUkZaUlVVUkZlRlo2WVZka2VtUkhPWGxhVXpGd1ltNVNiQXBqYlRGc1drZHNhR1JIVlhkSWFHTk9UV3BOZDAxcVJURk5WR3Q2VFhwTmVWZG9ZMDVOYWsxM1RXcEZNVTFVYXpCTmVrMTVWMnBCUVUxR2EzZEZkMWxJQ2t0dldrbDZhakJEUVZGWlNVdHZXa2w2YWpCRVFWRmpSRkZuUVVWV1YzSk9Na0Y1WXpOVk9EQlNRbTV4Y2taemMwTllja1pGVkdWNVRYTnJVV2hNUVZnS1lVOUJZbUZRZVd4TVlUWkhhWFZvY2xwVlJXUXJhVEpSSzJ0MmRHeFBTazQyVjNaS1lXOUphWEpIVlZWM09EUnpZMHRQUTBGdVRYZG5aMHAyVFVFMFJ3cEJNVlZrUkhkRlFpOTNVVVZCZDBsSVowUkJWRUpuVGxaSVUxVkZSRVJCUzBKblozSkNaMFZHUWxGalJFRjZRV1JDWjA1V1NGRTBSVVpuVVZWbldVNTVDa05hU0ZWd2EzcENabkZzWmxOb01pdGtWaTl1Y1djNGQwaDNXVVJXVWpCcVFrSm5kMFp2UVZVek9WQndlakZaYTBWYVlqVnhUbXB3UzBaWGFYaHBORmtLV2tRNGQySjNXVVJXVWpCU1FWRklMMEpIVlhkWk5GcG9ZVWhTTUdOSVRUWk1lVGx1WVZoU2IyUlhTWFZaTWpsMFRESjRhR1JZU214aWJsSjZZVmN4ZGdwaWFUbDNZMjA1TWxwWE5XaGliVTVzVEZjMWQySlRNVEJhV0U0d1RIazFibUZZVW05a1YwbDJaREk1ZVdFeVduTmlNMlI2VEROS2JHSkhWbWhqTWxWMUNtVlhNWE5SU0Vwc1dtNU5kbUZIVm1oYVNFMTJZbGRHY0dKcVFUVkNaMjl5UW1kRlJVRlpUeTlOUVVWQ1FrTjBiMlJJVW5kamVtOTJURE5TZG1FeVZuVUtURzFHYW1SSGJIWmliazExV2pKc01HRklWbWxrV0U1c1kyMU9kbUp1VW14aWJsRjFXVEk1ZEUxQ09FZERhWE5IUVZGUlFtYzNPSGRCVVVsRlJWaGtkZ3BqYlhSdFlrYzVNMWd5VW5Cak0wSm9aRWRPYjAxRVdVZERhWE5IUVZGUlFtYzNPSGRCVVUxRlMwUkZNbGx0Um1sYWJWcHBUMVJGTVUxNlozaE5WMVY0Q2s5VVRtcE5SRVUxVDFSTk5VMTZhM2hOZWxVelRYcGplVmxxU1RGWk1sVjNTbWRaUzB0M1dVSkNRVWRFZG5wQlFrSkJVVmxWU0ZacFlrZHNlbUZEUWxFS1dWZE9jbGxYWkd4SlNGSjJTVWMxZDJKWGNIcE5RelJIUTJselIwRlJVVUpuTnpoM1FWRlZSVWxIZUdoa1dFcHNZbTVTZW1GWE1YWmlhVGwzWTIwNU1ncGFWelZvWW0xT2JFeFhOWGRpVXpFd1dsaE9NRTFDTUVkRGFYTkhRVkZSUW1jM09IZEJVVmxGUkROS2JGcHVUWFpoUjFab1draE5kbUpYUm5CaWFrTkNDbWwzV1V0TGQxbENRa0ZJVjJWUlNVVkJaMUk1UWtoelFXVlJRak5CVGpBNVRVZHlSM2g0UlhsWmVHdGxTRXBzYms1M1MybFRiRFkwTTJwNWRDODBaVXNLWTI5QmRrdGxOazlCUVVGQ2FHeGhVbGhPVFVGQlFWRkVRVVZuZDFKblNXaEJUMXBaU0VNeVFYbENORTF0TlhWV05tVjBhV1ZuWTJSdlFqVjBMek5STmdwbE9IQmhhREpDU0RZd2RYSkJhVVZCZGpseWRqWlhUa2w1VUdaWWNsQXhlWHA1YTFGc1pIYzVhVVY0VTBKb0wySnlUazVxVkV4NlVDdDNXWGREWjFsSkNrdHZXa2w2YWpCRlFYZE5SRnAzUVhkYVFVbDNWQ3R1VDFWalIyMVVLMHN4WjNSVkwwVlVhVXBsZDFKVVdIUllOV0pxUm1nd1FVVkVWM3BXUm14TVVVc0theXREVFVOeUswTnRhRXBuWm05aVpEZ3pjWGRCYWtGNk9WZHdOQzlyY2tsbmVTdHhSRGR2WlVOM2JGVklOelJOVG1kWGNIa3lVVlUxVDNnelNqWXhkd3BRTWk4d1R6ZGlhRWcxWmtSaFIzUlpWVVpMV25wM1FUMEtMUzB0TFMxRlRrUWdRMFZTVkVsR1NVTkJWRVV0TFMwdExRbz0iLCJzaWciOiJUVVZWUTBsUlJFcGhhRlJ3VTI1c2RqWkllbFZxTW5reEwxQkNXVXhHZVRob2FFb3JOV1ZCUWxrM2RYazRVbEJ6UjFGSlowcFdkVXd6UjNJNWVXSXlWRkJWUlUxek5rbGxhVFZJVUVoaWVVZHNObWw0WjJRME1YbDJlVEEzVWxFOSJ9XX0sImhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIyYzVhZjNiZThjNzcxYzAwYzVhZGYwNDAxMzQ5YTg1NjM5NjA3Nzg4MzQwNjRhMmYyOTk5YzY4YmZiMWI0Njg4In0sInBheWxvYWRIYXNoIjp7ImFsZ29yaXRobSI6InNoYTI1NiIsInZhbHVlIjoiNjg5ZTE2NmNlM2I1Zjk5MTgxZDExYjcyYjg2OTJkODEwYjJlM2NkMTdmZWNiZjBiNzRmNDBmYTRmNmUzNjNkNSJ9fX19" + } + ], + "timestampVerificationData": null + }, + "dsseEnvelope": { + "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInN1YmplY3QiOlt7Im5hbWUiOiJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwiZGlnZXN0Ijp7InNoYTUxMiI6IjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIn19XSwicHJlZGljYXRlVHlwZSI6Imh0dHBzOi8vc2xzYS5kZXYvcHJvdmVuYW5jZS92MC4yIiwicHJlZGljYXRlIjp7ImJ1aWxkVHlwZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vY2xpL2doYUB2MSIsImJ1aWxkZXIiOnsiaWQiOiJodHRwczovL2dpdGh1Yi5jb20vbnBtL2NsaUA5LjUuMCJ9LCJpbnZvY2F0aW9uIjp7ImNvbmZpZ1NvdXJjZSI6eyJ1cmkiOiJnaXQraHR0cHM6Ly9naXRodWIuY29tL2xhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QHJlZnMvaGVhZHMvbWFpbiIsImRpZ2VzdCI6eyJzaGExIjoiMTZiYWJmZmI5MTUzODExZTE5M2MwMTk5MzkzOTEzNTczNzJiMjVjZSJ9LCJlbnRyeVBvaW50IjoibGF1cmVudHNpbW9uL3Byb3ZlbmFuY2UtbnBtLXRlc3QvLmdpdGh1Yi93b3JrZmxvd3MvcmVsZWFzZS55bWxAcmVmcy9oZWFkcy9tYWluIn0sInBhcmFtZXRlcnMiOnt9LCJlbnZpcm9ubWVudCI6eyJHSVRIVUJfQUNUT1JfSUQiOiI2NDUwNTA5OSIsIkdJVEhVQl9FVkVOVF9OQU1FIjoid29ya2Zsb3dfZGlzcGF0Y2giLCJHSVRIVUJfUkVGIjoicmVmcy9oZWFkcy9tYWluIiwiR0lUSFVCX1JFRl9UWVBFIjoiYnJhbmNoIiwiR0lUSFVCX1JFUE9TSVRPUlkiOiJsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsIkdJVEhVQl9SRVBPU0lUT1JZX0lEIjoiNjAyMjIzOTQ1IiwiR0lUSFVCX1JFUE9TSVRPUllfT1dORVJfSUQiOiI2NDUwNTA5OSIsIkdJVEhVQl9SVU5fQVRURU1QVCI6IjEiLCJHSVRIVUJfUlVOX0lEIjoiNDE4NzQ2NDU3NyIsIkdJVEhVQl9SVU5fTlVNQkVSIjoiMiIsIkdJVEhVQl9TSEEiOiIxNmJhYmZmYjkxNTM4MTFlMTkzYzAxOTkzOTM5MTM1NzM3MmIyNWNlIiwiR0lUSFVCX1dPUktGTE9XX1JFRiI6ImxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbiIsIkdJVEhVQl9XT1JLRkxPV19TSEEiOiIxNmJhYmZmYjkxNTM4MTFlMTkzYzAxOTkzOTM5MTM1NzM3MmIyNWNlIn19LCJtZXRhZGF0YSI6eyJidWlsZEludm9jYXRpb25JZCI6IjQxODc0NjQ1NzctMSIsImNvbXBsZXRlbmVzcyI6eyJwYXJhbWV0ZXJzIjpmYWxzZSwiZW52aXJvbm1lbnQiOmZhbHNlLCJtYXRlcmlhbHMiOmZhbHNlfSwicmVwcm9kdWNpYmxlIjpmYWxzZX0sIm1hdGVyaWFscyI6W3sidXJpIjoiZ2l0K2h0dHBzOi8vZ2l0aHViLmNvbS9sYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsImRpZ2VzdCI6eyJzaGExIjoiMTZiYWJmZmI5MTUzODExZTE5M2MwMTk5MzkzOTEzNTczNzJiMjVjZSJ9fV19fQ==", + "payloadType": "application/vnd.in-toto+jsonA", + "signatures": [ + { + "sig": "MEUCIQDJahTpSnlv6HzUj2y1/PBYLFy8hhJ+5eABY7uy8RPsGQIgJVuL3Gr9yb2TPUEMs6Iei5HPHbyGl6ixgd41yvy07RQ=", + "keyid": "" + } + ] + } + } + }, + { + "predicateType": "https://github.com/npm/attestation/tree/main/specs/publish/v0.1", + "bundle": { + "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.1", + "verificationMaterial": { + "publicKey": { + "hint": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA" + }, + "tlogEntries": [ + { + "logIndex": "13420289", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "intoto", + "version": "0.0.2" + }, + "integratedTime": "1676489615", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCICYgQbiFj7t0A9B/p4Hkq5H0gB41InPBFFnhEeuP4Fo0AiEA7fGqVACs5cFpoQGHX8HVDq/jKBWbS0gutPXpcOz6r6g=" + }, + "inclusionProof": null, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7ImtleWlkIjoiU0hBMjU2OmpsM2J3c3d1ODBQampva0NnaDBvMnc1YzJVNExoUUFFNTdnajljejFrekEiLCJwdWJsaWNLZXkiOiJMUzB0TFMxQ1JVZEpUaUJRVlVKTVNVTWdTMFZaTFMwdExTMEtUVVpyZDBWM1dVaExiMXBKZW1vd1EwRlJXVWxMYjFwSmVtb3dSRUZSWTBSUlowRkZNVTlzWWpONlRVRkdSbmhZUzBocFNXdFJUelZqU2pOWmFHdzFhVFpWVUhBclNXaDFkR1ZDU21KMVNHTkJOVlZ2WjB0dk1FVlhkR3hYZDFjMlMxTmhTMjlVVGtWWlREZEtiRU5SYVZadWEyaENhM1JWWjJjOVBRb3RMUzB0TFVWT1JDQlFWVUpNU1VNZ1MwVlpMUzB0TFMwPSIsInNpZyI6IlRVVlJRMGxETURGaFJqbFFZVWxtSzNOcVkzRlBiVzQwUVZaVU56bFBWMFJuVkZGVk5XVXZiVkp0TVcweVNIWjVRV2xCY0hCNk1FWkxWVzFEVjJwdVUyUnJORzB5VkdGTlpXMXFSRXRqUlcxTVdFSTRWVVpFTlZsYWRETTJaejA5In1dfSwiaGFzaCI6eyJhbGdvcml0aG0iOiJzaGEyNTYiLCJ2YWx1ZSI6IjkxNDU3YjdiYzg1NTgwY2Y2NTAxNDM5NDU5ZDYyOWI0YzBlOTUxNmFjNzc3NTllNGQwNzMwZjVlMTUxNjRkMDcifSwicGF5bG9hZEhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI1ZmFmZTQwMmJiYzBiMTNhMmFmMmIzMjhjYmNjNmFiZTlmZTA1MGRkNDUzNjNkNTE1YWIyYzk4MjA3NDMwNjVkIn19fX0=" + } + ], + "timestampVerificationData": null + }, + "dsseEnvelope": { + "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInN1YmplY3QiOlt7Im5hbWUiOiJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwiZGlnZXN0Ijp7InNoYTUxMiI6IjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIn19XSwicHJlZGljYXRlVHlwZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsInByZWRpY2F0ZSI6eyJuYW1lIjoiQGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0IiwidmVyc2lvbiI6IjEuMC4wIiwicmVnaXN0cnkiOiJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyJ9fQ==", + "payloadType": "application/vnd.in-toto+json", + "signatures": [ + { + "sig": "MEQCIC01aF9PaIf+sjcqOmn4AVT79OWDgTQU5e/mRm1m2HvyAiAppz0FKUmCWjnSdk4m2TaMemjDKcEmLXB8UFD5YZt36g==", + "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA" + } + ] + } + } + } +] diff --git a/verifiers/internal/gha/testdata/npm-att-mismatch-prov-predicatetype.intoto.sigstore b/verifiers/internal/gha/testdata/npm-att-mismatch-prov-predicatetype.intoto.sigstore new file mode 100644 index 0000000..6e11e91 --- /dev/null +++ b/verifiers/internal/gha/testdata/npm-att-mismatch-prov-predicatetype.intoto.sigstore @@ -0,0 +1,92 @@ +[ + { + "predicateType": "https://slsa.dev/provenanc/v0.2", + "bundle": { + "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.1", + "verificationMaterial": { + "x509CertificateChain": { + "certificates": [ + { + "rawBytes": "MIIDzTCCA1SgAwIBAgIUSUNeEjOTOlxw2mAmVuog6waz+NcwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjMwMjE1MTkzMzMyWhcNMjMwMjE1MTk0MzMyWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVWrN2Ayc3U80RBnqrFssCXrFETeyMskQhLAXaOAbaPylLa6GiuhrZUEd+i2Q+kvtlOJN6WvJaoIirGUUw84scKOCAnMwggJvMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUgYNyCZHUpkzBfqlfSh2+dV/nqg8wHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wbwYDVR0RAQH/BGUwY4ZhaHR0cHM6Ly9naXRodWIuY29tL2xhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbjA5BgorBgEEAYO/MAEBBCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMB8GCisGAQQBg78wAQIEEXdvcmtmbG93X2Rpc3BhdGNoMDYGCisGAQQBg78wAQMEKDE2YmFiZmZiOTE1MzgxMWUxOTNjMDE5OTM5MzkxMzU3MzcyYjI1Y2UwJgYKKwYBBAGDvzABBAQYUHVibGlzaCBQYWNrYWdlIHRvIG5wbWpzMC4GCisGAQQBg78wAQUEIGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0MB0GCisGAQQBg78wAQYED3JlZnMvaGVhZHMvbWFpbjCBiwYKKwYBBAHWeQIEAgR9BHsAeQB3AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABhlaRXNMAAAQDAEgwRgIhAOZYHC2AyB4Mm5uV6etiegcdoB5t/3Q6e8pah2BH60urAiEAv9rv6WNIyPfXrP1yzykQldw9iExSBh/brNNjTLzP+wYwCgYIKoZIzj0EAwMDZwAwZAIwT+nOUcGmT+K1gtU/ETiJewRTXtX5bjFh0AEDWzVFlLQKk+CMCr+CmhJgfobd83qwAjAz9Wp4/krIgy+qD7oeCwlUH74MNgWpy2QU5Ox3J61wP2/0O7bhH5fDaGtYUFKZzwA=" + }, + { + "rawBytes": "MIICGjCCAaGgAwIBAgIUALnViVfnU0brJasmRkHrn/UnfaQwCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMjA0MTMyMDA2MTVaFw0zMTEwMDUxMzU2NThaMDcxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEeMBwGA1UEAxMVc2lnc3RvcmUtaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8RVS/ysH+NOvuDZyPIZtilgUF9NlarYpAd9HP1vBBH1U5CV77LSS7s0ZiH4nE7Hv7ptS6LvvR/STk798LVgMzLlJ4HeIfF3tHSaexLcYpSASr1kS0N/RgBJz/9jWCiXno3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU39Ppz1YkEZb5qNjpKFWixi4YZD8wHwYDVR0jBBgwFoAUWMAeX5FFpWapesyQoZMi0CrFxfowCgYIKoZIzj0EAwMDZwAwZAIwPCsQK4DYiZYDPIaDi5HFKnfxXx6ASSVmERfsynYBiX2X6SJRnZU84/9DZdnFvvxmAjBOt6QpBlc4J/0DxvkTCqpclvziL6BCCPnjdlIB3Pu3BxsPmygUY7Ii2zbdCdliiow=" + }, + { + "rawBytes": "MIIB9zCCAXygAwIBAgIUALZNAPFdxHPwjeDloDwyYChAO/4wCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMTEwMDcxMzU2NTlaFw0zMTEwMDUxMzU2NThaMCoxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjERMA8GA1UEAxMIc2lnc3RvcmUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT7XeFT4rb3PQGwS4IajtLk3/OlnpgangaBclYpsYBr5i+4ynB07ceb3LP0OIOZdxexX69c5iVuyJRQ+Hz05yi+UF3uBWAlHpiS5sh0+H2GHE7SXrk1EC5m1Tr19L9gg92jYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRYwB5fkUWlZql6zJChkyLQKsXF+jAfBgNVHSMEGDAWgBRYwB5fkUWlZql6zJChkyLQKsXF+jAKBggqhkjOPQQDAwNpADBmAjEAj1nHeXZp+13NWBNa+EDsDP8G1WWg1tCMWP/WHPqpaVo0jhsweNFZgSs0eE7wYI4qAjEA2WB9ot98sIkoF3vZYdd3/VtWB5b9TNMea7Ix/stJ5TfcLLeABLE4BNJOsQ4vnBHJ" + } + ] + }, + "tlogEntries": [ + { + "logIndex": "13420286", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "intoto", + "version": "0.0.2" + }, + "integratedTime": "1676489612", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCIG/LjJ5tqTgKvbA0F+96CJHIk2X0S+9cBz1Z04BfU7dLAiEA7cpf1Agv0VyEu0wR41nEZ9AZ6GVaYR5rf4AAYIZr4hk=" + }, + "inclusionProof": null, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7InB1YmxpY0tleSI6IkxTMHRMUzFDUlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVI2VkVORFFURlRaMEYzU1VKQlowbFZVMVZPWlVWcVQxUlBiSGgzTW0xQmJWWjFiMmMyZDJGNkswNWpkME5uV1VsTGIxcEplbW93UlVGM1RYY0tUbnBGVmsxQ1RVZEJNVlZGUTJoTlRXTXliRzVqTTFKMlkyMVZkVnBIVmpKTlVqUjNTRUZaUkZaUlVVUkZlRlo2WVZka2VtUkhPWGxhVXpGd1ltNVNiQXBqYlRGc1drZHNhR1JIVlhkSWFHTk9UV3BOZDAxcVJURk5WR3Q2VFhwTmVWZG9ZMDVOYWsxM1RXcEZNVTFVYXpCTmVrMTVWMnBCUVUxR2EzZEZkMWxJQ2t0dldrbDZhakJEUVZGWlNVdHZXa2w2YWpCRVFWRmpSRkZuUVVWV1YzSk9Na0Y1WXpOVk9EQlNRbTV4Y2taemMwTllja1pGVkdWNVRYTnJVV2hNUVZnS1lVOUJZbUZRZVd4TVlUWkhhWFZvY2xwVlJXUXJhVEpSSzJ0MmRHeFBTazQyVjNaS1lXOUphWEpIVlZWM09EUnpZMHRQUTBGdVRYZG5aMHAyVFVFMFJ3cEJNVlZrUkhkRlFpOTNVVVZCZDBsSVowUkJWRUpuVGxaSVUxVkZSRVJCUzBKblozSkNaMFZHUWxGalJFRjZRV1JDWjA1V1NGRTBSVVpuVVZWbldVNTVDa05hU0ZWd2EzcENabkZzWmxOb01pdGtWaTl1Y1djNGQwaDNXVVJXVWpCcVFrSm5kMFp2UVZVek9WQndlakZaYTBWYVlqVnhUbXB3UzBaWGFYaHBORmtLV2tRNGQySjNXVVJXVWpCU1FWRklMMEpIVlhkWk5GcG9ZVWhTTUdOSVRUWk1lVGx1WVZoU2IyUlhTWFZaTWpsMFRESjRhR1JZU214aWJsSjZZVmN4ZGdwaWFUbDNZMjA1TWxwWE5XaGliVTVzVEZjMWQySlRNVEJhV0U0d1RIazFibUZZVW05a1YwbDJaREk1ZVdFeVduTmlNMlI2VEROS2JHSkhWbWhqTWxWMUNtVlhNWE5SU0Vwc1dtNU5kbUZIVm1oYVNFMTJZbGRHY0dKcVFUVkNaMjl5UW1kRlJVRlpUeTlOUVVWQ1FrTjBiMlJJVW5kamVtOTJURE5TZG1FeVZuVUtURzFHYW1SSGJIWmliazExV2pKc01HRklWbWxrV0U1c1kyMU9kbUp1VW14aWJsRjFXVEk1ZEUxQ09FZERhWE5IUVZGUlFtYzNPSGRCVVVsRlJWaGtkZ3BqYlhSdFlrYzVNMWd5VW5Cak0wSm9aRWRPYjAxRVdVZERhWE5IUVZGUlFtYzNPSGRCVVUxRlMwUkZNbGx0Um1sYWJWcHBUMVJGTVUxNlozaE5WMVY0Q2s5VVRtcE5SRVUxVDFSTk5VMTZhM2hOZWxVelRYcGplVmxxU1RGWk1sVjNTbWRaUzB0M1dVSkNRVWRFZG5wQlFrSkJVVmxWU0ZacFlrZHNlbUZEUWxFS1dWZE9jbGxYWkd4SlNGSjJTVWMxZDJKWGNIcE5RelJIUTJselIwRlJVVUpuTnpoM1FWRlZSVWxIZUdoa1dFcHNZbTVTZW1GWE1YWmlhVGwzWTIwNU1ncGFWelZvWW0xT2JFeFhOWGRpVXpFd1dsaE9NRTFDTUVkRGFYTkhRVkZSUW1jM09IZEJVVmxGUkROS2JGcHVUWFpoUjFab1draE5kbUpYUm5CaWFrTkNDbWwzV1V0TGQxbENRa0ZJVjJWUlNVVkJaMUk1UWtoelFXVlJRak5CVGpBNVRVZHlSM2g0UlhsWmVHdGxTRXBzYms1M1MybFRiRFkwTTJwNWRDODBaVXNLWTI5QmRrdGxOazlCUVVGQ2FHeGhVbGhPVFVGQlFWRkVRVVZuZDFKblNXaEJUMXBaU0VNeVFYbENORTF0TlhWV05tVjBhV1ZuWTJSdlFqVjBMek5STmdwbE9IQmhhREpDU0RZd2RYSkJhVVZCZGpseWRqWlhUa2w1VUdaWWNsQXhlWHA1YTFGc1pIYzVhVVY0VTBKb0wySnlUazVxVkV4NlVDdDNXWGREWjFsSkNrdHZXa2w2YWpCRlFYZE5SRnAzUVhkYVFVbDNWQ3R1VDFWalIyMVVLMHN4WjNSVkwwVlVhVXBsZDFKVVdIUllOV0pxUm1nd1FVVkVWM3BXUm14TVVVc0theXREVFVOeUswTnRhRXBuWm05aVpEZ3pjWGRCYWtGNk9WZHdOQzlyY2tsbmVTdHhSRGR2WlVOM2JGVklOelJOVG1kWGNIa3lVVlUxVDNnelNqWXhkd3BRTWk4d1R6ZGlhRWcxWmtSaFIzUlpWVVpMV25wM1FUMEtMUzB0TFMxRlRrUWdRMFZTVkVsR1NVTkJWRVV0TFMwdExRbz0iLCJzaWciOiJUVVZWUTBsUlJFcGhhRlJ3VTI1c2RqWkllbFZxTW5reEwxQkNXVXhHZVRob2FFb3JOV1ZCUWxrM2RYazRVbEJ6UjFGSlowcFdkVXd6UjNJNWVXSXlWRkJWUlUxek5rbGxhVFZJVUVoaWVVZHNObWw0WjJRME1YbDJlVEEzVWxFOSJ9XX0sImhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIyYzVhZjNiZThjNzcxYzAwYzVhZGYwNDAxMzQ5YTg1NjM5NjA3Nzg4MzQwNjRhMmYyOTk5YzY4YmZiMWI0Njg4In0sInBheWxvYWRIYXNoIjp7ImFsZ29yaXRobSI6InNoYTI1NiIsInZhbHVlIjoiNjg5ZTE2NmNlM2I1Zjk5MTgxZDExYjcyYjg2OTJkODEwYjJlM2NkMTdmZWNiZjBiNzRmNDBmYTRmNmUzNjNkNSJ9fX19" + } + ], + "timestampVerificationData": null + }, + "dsseEnvelope": { + "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInN1YmplY3QiOlt7Im5hbWUiOiJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwiZGlnZXN0Ijp7InNoYTUxMiI6IjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIn19XSwicHJlZGljYXRlVHlwZSI6Imh0dHBzOi8vc2xzYS5kZXYvcHJvdmVuYW5jZS92MC4yIiwicHJlZGljYXRlIjp7ImJ1aWxkVHlwZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vY2xpL2doYUB2MSIsImJ1aWxkZXIiOnsiaWQiOiJodHRwczovL2dpdGh1Yi5jb20vbnBtL2NsaUA5LjUuMCJ9LCJpbnZvY2F0aW9uIjp7ImNvbmZpZ1NvdXJjZSI6eyJ1cmkiOiJnaXQraHR0cHM6Ly9naXRodWIuY29tL2xhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QHJlZnMvaGVhZHMvbWFpbiIsImRpZ2VzdCI6eyJzaGExIjoiMTZiYWJmZmI5MTUzODExZTE5M2MwMTk5MzkzOTEzNTczNzJiMjVjZSJ9LCJlbnRyeVBvaW50IjoibGF1cmVudHNpbW9uL3Byb3ZlbmFuY2UtbnBtLXRlc3QvLmdpdGh1Yi93b3JrZmxvd3MvcmVsZWFzZS55bWxAcmVmcy9oZWFkcy9tYWluIn0sInBhcmFtZXRlcnMiOnt9LCJlbnZpcm9ubWVudCI6eyJHSVRIVUJfQUNUT1JfSUQiOiI2NDUwNTA5OSIsIkdJVEhVQl9FVkVOVF9OQU1FIjoid29ya2Zsb3dfZGlzcGF0Y2giLCJHSVRIVUJfUkVGIjoicmVmcy9oZWFkcy9tYWluIiwiR0lUSFVCX1JFRl9UWVBFIjoiYnJhbmNoIiwiR0lUSFVCX1JFUE9TSVRPUlkiOiJsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsIkdJVEhVQl9SRVBPU0lUT1JZX0lEIjoiNjAyMjIzOTQ1IiwiR0lUSFVCX1JFUE9TSVRPUllfT1dORVJfSUQiOiI2NDUwNTA5OSIsIkdJVEhVQl9SVU5fQVRURU1QVCI6IjEiLCJHSVRIVUJfUlVOX0lEIjoiNDE4NzQ2NDU3NyIsIkdJVEhVQl9SVU5fTlVNQkVSIjoiMiIsIkdJVEhVQl9TSEEiOiIxNmJhYmZmYjkxNTM4MTFlMTkzYzAxOTkzOTM5MTM1NzM3MmIyNWNlIiwiR0lUSFVCX1dPUktGTE9XX1JFRiI6ImxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbiIsIkdJVEhVQl9XT1JLRkxPV19TSEEiOiIxNmJhYmZmYjkxNTM4MTFlMTkzYzAxOTkzOTM5MTM1NzM3MmIyNWNlIn19LCJtZXRhZGF0YSI6eyJidWlsZEludm9jYXRpb25JZCI6IjQxODc0NjQ1NzctMSIsImNvbXBsZXRlbmVzcyI6eyJwYXJhbWV0ZXJzIjpmYWxzZSwiZW52aXJvbm1lbnQiOmZhbHNlLCJtYXRlcmlhbHMiOmZhbHNlfSwicmVwcm9kdWNpYmxlIjpmYWxzZX0sIm1hdGVyaWFscyI6W3sidXJpIjoiZ2l0K2h0dHBzOi8vZ2l0aHViLmNvbS9sYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsImRpZ2VzdCI6eyJzaGExIjoiMTZiYWJmZmI5MTUzODExZTE5M2MwMTk5MzkzOTEzNTczNzJiMjVjZSJ9fV19fQ==", + "payloadType": "application/vnd.in-toto+json", + "signatures": [ + { + "sig": "MEUCIQDJahTpSnlv6HzUj2y1/PBYLFy8hhJ+5eABY7uy8RPsGQIgJVuL3Gr9yb2TPUEMs6Iei5HPHbyGl6ixgd41yvy07RQ=", + "keyid": "" + } + ] + } + } + }, + { + "predicateType": "https://github.com/npm/attestation/tree/main/specs/publish/v0.1", + "bundle": { + "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.1", + "verificationMaterial": { + "publicKey": { + "hint": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA" + }, + "tlogEntries": [ + { + "logIndex": "13420289", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "intoto", + "version": "0.0.2" + }, + "integratedTime": "1676489615", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCICYgQbiFj7t0A9B/p4Hkq5H0gB41InPBFFnhEeuP4Fo0AiEA7fGqVACs5cFpoQGHX8HVDq/jKBWbS0gutPXpcOz6r6g=" + }, + "inclusionProof": null, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7ImtleWlkIjoiU0hBMjU2OmpsM2J3c3d1ODBQampva0NnaDBvMnc1YzJVNExoUUFFNTdnajljejFrekEiLCJwdWJsaWNLZXkiOiJMUzB0TFMxQ1JVZEpUaUJRVlVKTVNVTWdTMFZaTFMwdExTMEtUVVpyZDBWM1dVaExiMXBKZW1vd1EwRlJXVWxMYjFwSmVtb3dSRUZSWTBSUlowRkZNVTlzWWpONlRVRkdSbmhZUzBocFNXdFJUelZqU2pOWmFHdzFhVFpWVUhBclNXaDFkR1ZDU21KMVNHTkJOVlZ2WjB0dk1FVlhkR3hYZDFjMlMxTmhTMjlVVGtWWlREZEtiRU5SYVZadWEyaENhM1JWWjJjOVBRb3RMUzB0TFVWT1JDQlFWVUpNU1VNZ1MwVlpMUzB0TFMwPSIsInNpZyI6IlRVVlJRMGxETURGaFJqbFFZVWxtSzNOcVkzRlBiVzQwUVZaVU56bFBWMFJuVkZGVk5XVXZiVkp0TVcweVNIWjVRV2xCY0hCNk1FWkxWVzFEVjJwdVUyUnJORzB5VkdGTlpXMXFSRXRqUlcxTVdFSTRWVVpFTlZsYWRETTJaejA5In1dfSwiaGFzaCI6eyJhbGdvcml0aG0iOiJzaGEyNTYiLCJ2YWx1ZSI6IjkxNDU3YjdiYzg1NTgwY2Y2NTAxNDM5NDU5ZDYyOWI0YzBlOTUxNmFjNzc3NTllNGQwNzMwZjVlMTUxNjRkMDcifSwicGF5bG9hZEhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI1ZmFmZTQwMmJiYzBiMTNhMmFmMmIzMjhjYmNjNmFiZTlmZTA1MGRkNDUzNjNkNTE1YWIyYzk4MjA3NDMwNjVkIn19fX0=" + } + ], + "timestampVerificationData": null + }, + "dsseEnvelope": { + "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInN1YmplY3QiOlt7Im5hbWUiOiJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwiZGlnZXN0Ijp7InNoYTUxMiI6IjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIn19XSwicHJlZGljYXRlVHlwZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsInByZWRpY2F0ZSI6eyJuYW1lIjoiQGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0IiwidmVyc2lvbiI6IjEuMC4wIiwicmVnaXN0cnkiOiJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyJ9fQ==", + "payloadType": "application/vnd.in-toto+json", + "signatures": [ + { + "sig": "MEQCIC01aF9PaIf+sjcqOmn4AVT79OWDgTQU5e/mRm1m2HvyAiAppz0FKUmCWjnSdk4m2TaMemjDKcEmLXB8UFD5YZt36g==", + "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA" + } + ] + } + } + } +] diff --git a/verifiers/internal/gha/testdata/npm-att-mismatch-pub-payloadtype.intoto.sigstore b/verifiers/internal/gha/testdata/npm-att-mismatch-pub-payloadtype.intoto.sigstore new file mode 100644 index 0000000..617235b --- /dev/null +++ b/verifiers/internal/gha/testdata/npm-att-mismatch-pub-payloadtype.intoto.sigstore @@ -0,0 +1,92 @@ +[ + { + "predicateType": "https://slsa.dev/provenance/v0.2", + "bundle": { + "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.1", + "verificationMaterial": { + "x509CertificateChain": { + "certificates": [ + { + "rawBytes": "MIIDzTCCA1SgAwIBAgIUSUNeEjOTOlxw2mAmVuog6waz+NcwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjMwMjE1MTkzMzMyWhcNMjMwMjE1MTk0MzMyWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVWrN2Ayc3U80RBnqrFssCXrFETeyMskQhLAXaOAbaPylLa6GiuhrZUEd+i2Q+kvtlOJN6WvJaoIirGUUw84scKOCAnMwggJvMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUgYNyCZHUpkzBfqlfSh2+dV/nqg8wHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wbwYDVR0RAQH/BGUwY4ZhaHR0cHM6Ly9naXRodWIuY29tL2xhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbjA5BgorBgEEAYO/MAEBBCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMB8GCisGAQQBg78wAQIEEXdvcmtmbG93X2Rpc3BhdGNoMDYGCisGAQQBg78wAQMEKDE2YmFiZmZiOTE1MzgxMWUxOTNjMDE5OTM5MzkxMzU3MzcyYjI1Y2UwJgYKKwYBBAGDvzABBAQYUHVibGlzaCBQYWNrYWdlIHRvIG5wbWpzMC4GCisGAQQBg78wAQUEIGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0MB0GCisGAQQBg78wAQYED3JlZnMvaGVhZHMvbWFpbjCBiwYKKwYBBAHWeQIEAgR9BHsAeQB3AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABhlaRXNMAAAQDAEgwRgIhAOZYHC2AyB4Mm5uV6etiegcdoB5t/3Q6e8pah2BH60urAiEAv9rv6WNIyPfXrP1yzykQldw9iExSBh/brNNjTLzP+wYwCgYIKoZIzj0EAwMDZwAwZAIwT+nOUcGmT+K1gtU/ETiJewRTXtX5bjFh0AEDWzVFlLQKk+CMCr+CmhJgfobd83qwAjAz9Wp4/krIgy+qD7oeCwlUH74MNgWpy2QU5Ox3J61wP2/0O7bhH5fDaGtYUFKZzwA=" + }, + { + "rawBytes": "MIICGjCCAaGgAwIBAgIUALnViVfnU0brJasmRkHrn/UnfaQwCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMjA0MTMyMDA2MTVaFw0zMTEwMDUxMzU2NThaMDcxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEeMBwGA1UEAxMVc2lnc3RvcmUtaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8RVS/ysH+NOvuDZyPIZtilgUF9NlarYpAd9HP1vBBH1U5CV77LSS7s0ZiH4nE7Hv7ptS6LvvR/STk798LVgMzLlJ4HeIfF3tHSaexLcYpSASr1kS0N/RgBJz/9jWCiXno3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU39Ppz1YkEZb5qNjpKFWixi4YZD8wHwYDVR0jBBgwFoAUWMAeX5FFpWapesyQoZMi0CrFxfowCgYIKoZIzj0EAwMDZwAwZAIwPCsQK4DYiZYDPIaDi5HFKnfxXx6ASSVmERfsynYBiX2X6SJRnZU84/9DZdnFvvxmAjBOt6QpBlc4J/0DxvkTCqpclvziL6BCCPnjdlIB3Pu3BxsPmygUY7Ii2zbdCdliiow=" + }, + { + "rawBytes": "MIIB9zCCAXygAwIBAgIUALZNAPFdxHPwjeDloDwyYChAO/4wCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMTEwMDcxMzU2NTlaFw0zMTEwMDUxMzU2NThaMCoxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjERMA8GA1UEAxMIc2lnc3RvcmUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT7XeFT4rb3PQGwS4IajtLk3/OlnpgangaBclYpsYBr5i+4ynB07ceb3LP0OIOZdxexX69c5iVuyJRQ+Hz05yi+UF3uBWAlHpiS5sh0+H2GHE7SXrk1EC5m1Tr19L9gg92jYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRYwB5fkUWlZql6zJChkyLQKsXF+jAfBgNVHSMEGDAWgBRYwB5fkUWlZql6zJChkyLQKsXF+jAKBggqhkjOPQQDAwNpADBmAjEAj1nHeXZp+13NWBNa+EDsDP8G1WWg1tCMWP/WHPqpaVo0jhsweNFZgSs0eE7wYI4qAjEA2WB9ot98sIkoF3vZYdd3/VtWB5b9TNMea7Ix/stJ5TfcLLeABLE4BNJOsQ4vnBHJ" + } + ] + }, + "tlogEntries": [ + { + "logIndex": "13420286", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "intoto", + "version": "0.0.2" + }, + "integratedTime": "1676489612", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCIG/LjJ5tqTgKvbA0F+96CJHIk2X0S+9cBz1Z04BfU7dLAiEA7cpf1Agv0VyEu0wR41nEZ9AZ6GVaYR5rf4AAYIZr4hk=" + }, + "inclusionProof": null, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7InB1YmxpY0tleSI6IkxTMHRMUzFDUlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVI2VkVORFFURlRaMEYzU1VKQlowbFZVMVZPWlVWcVQxUlBiSGgzTW0xQmJWWjFiMmMyZDJGNkswNWpkME5uV1VsTGIxcEplbW93UlVGM1RYY0tUbnBGVmsxQ1RVZEJNVlZGUTJoTlRXTXliRzVqTTFKMlkyMVZkVnBIVmpKTlVqUjNTRUZaUkZaUlVVUkZlRlo2WVZka2VtUkhPWGxhVXpGd1ltNVNiQXBqYlRGc1drZHNhR1JIVlhkSWFHTk9UV3BOZDAxcVJURk5WR3Q2VFhwTmVWZG9ZMDVOYWsxM1RXcEZNVTFVYXpCTmVrMTVWMnBCUVUxR2EzZEZkMWxJQ2t0dldrbDZhakJEUVZGWlNVdHZXa2w2YWpCRVFWRmpSRkZuUVVWV1YzSk9Na0Y1WXpOVk9EQlNRbTV4Y2taemMwTllja1pGVkdWNVRYTnJVV2hNUVZnS1lVOUJZbUZRZVd4TVlUWkhhWFZvY2xwVlJXUXJhVEpSSzJ0MmRHeFBTazQyVjNaS1lXOUphWEpIVlZWM09EUnpZMHRQUTBGdVRYZG5aMHAyVFVFMFJ3cEJNVlZrUkhkRlFpOTNVVVZCZDBsSVowUkJWRUpuVGxaSVUxVkZSRVJCUzBKblozSkNaMFZHUWxGalJFRjZRV1JDWjA1V1NGRTBSVVpuVVZWbldVNTVDa05hU0ZWd2EzcENabkZzWmxOb01pdGtWaTl1Y1djNGQwaDNXVVJXVWpCcVFrSm5kMFp2UVZVek9WQndlakZaYTBWYVlqVnhUbXB3UzBaWGFYaHBORmtLV2tRNGQySjNXVVJXVWpCU1FWRklMMEpIVlhkWk5GcG9ZVWhTTUdOSVRUWk1lVGx1WVZoU2IyUlhTWFZaTWpsMFRESjRhR1JZU214aWJsSjZZVmN4ZGdwaWFUbDNZMjA1TWxwWE5XaGliVTVzVEZjMWQySlRNVEJhV0U0d1RIazFibUZZVW05a1YwbDJaREk1ZVdFeVduTmlNMlI2VEROS2JHSkhWbWhqTWxWMUNtVlhNWE5SU0Vwc1dtNU5kbUZIVm1oYVNFMTJZbGRHY0dKcVFUVkNaMjl5UW1kRlJVRlpUeTlOUVVWQ1FrTjBiMlJJVW5kamVtOTJURE5TZG1FeVZuVUtURzFHYW1SSGJIWmliazExV2pKc01HRklWbWxrV0U1c1kyMU9kbUp1VW14aWJsRjFXVEk1ZEUxQ09FZERhWE5IUVZGUlFtYzNPSGRCVVVsRlJWaGtkZ3BqYlhSdFlrYzVNMWd5VW5Cak0wSm9aRWRPYjAxRVdVZERhWE5IUVZGUlFtYzNPSGRCVVUxRlMwUkZNbGx0Um1sYWJWcHBUMVJGTVUxNlozaE5WMVY0Q2s5VVRtcE5SRVUxVDFSTk5VMTZhM2hOZWxVelRYcGplVmxxU1RGWk1sVjNTbWRaUzB0M1dVSkNRVWRFZG5wQlFrSkJVVmxWU0ZacFlrZHNlbUZEUWxFS1dWZE9jbGxYWkd4SlNGSjJTVWMxZDJKWGNIcE5RelJIUTJselIwRlJVVUpuTnpoM1FWRlZSVWxIZUdoa1dFcHNZbTVTZW1GWE1YWmlhVGwzWTIwNU1ncGFWelZvWW0xT2JFeFhOWGRpVXpFd1dsaE9NRTFDTUVkRGFYTkhRVkZSUW1jM09IZEJVVmxGUkROS2JGcHVUWFpoUjFab1draE5kbUpYUm5CaWFrTkNDbWwzV1V0TGQxbENRa0ZJVjJWUlNVVkJaMUk1UWtoelFXVlJRak5CVGpBNVRVZHlSM2g0UlhsWmVHdGxTRXBzYms1M1MybFRiRFkwTTJwNWRDODBaVXNLWTI5QmRrdGxOazlCUVVGQ2FHeGhVbGhPVFVGQlFWRkVRVVZuZDFKblNXaEJUMXBaU0VNeVFYbENORTF0TlhWV05tVjBhV1ZuWTJSdlFqVjBMek5STmdwbE9IQmhhREpDU0RZd2RYSkJhVVZCZGpseWRqWlhUa2w1VUdaWWNsQXhlWHA1YTFGc1pIYzVhVVY0VTBKb0wySnlUazVxVkV4NlVDdDNXWGREWjFsSkNrdHZXa2w2YWpCRlFYZE5SRnAzUVhkYVFVbDNWQ3R1VDFWalIyMVVLMHN4WjNSVkwwVlVhVXBsZDFKVVdIUllOV0pxUm1nd1FVVkVWM3BXUm14TVVVc0theXREVFVOeUswTnRhRXBuWm05aVpEZ3pjWGRCYWtGNk9WZHdOQzlyY2tsbmVTdHhSRGR2WlVOM2JGVklOelJOVG1kWGNIa3lVVlUxVDNnelNqWXhkd3BRTWk4d1R6ZGlhRWcxWmtSaFIzUlpWVVpMV25wM1FUMEtMUzB0TFMxRlRrUWdRMFZTVkVsR1NVTkJWRVV0TFMwdExRbz0iLCJzaWciOiJUVVZWUTBsUlJFcGhhRlJ3VTI1c2RqWkllbFZxTW5reEwxQkNXVXhHZVRob2FFb3JOV1ZCUWxrM2RYazRVbEJ6UjFGSlowcFdkVXd6UjNJNWVXSXlWRkJWUlUxek5rbGxhVFZJVUVoaWVVZHNObWw0WjJRME1YbDJlVEEzVWxFOSJ9XX0sImhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIyYzVhZjNiZThjNzcxYzAwYzVhZGYwNDAxMzQ5YTg1NjM5NjA3Nzg4MzQwNjRhMmYyOTk5YzY4YmZiMWI0Njg4In0sInBheWxvYWRIYXNoIjp7ImFsZ29yaXRobSI6InNoYTI1NiIsInZhbHVlIjoiNjg5ZTE2NmNlM2I1Zjk5MTgxZDExYjcyYjg2OTJkODEwYjJlM2NkMTdmZWNiZjBiNzRmNDBmYTRmNmUzNjNkNSJ9fX19" + } + ], + "timestampVerificationData": null + }, + "dsseEnvelope": { + "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInN1YmplY3QiOlt7Im5hbWUiOiJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwiZGlnZXN0Ijp7InNoYTUxMiI6IjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIn19XSwicHJlZGljYXRlVHlwZSI6Imh0dHBzOi8vc2xzYS5kZXYvcHJvdmVuYW5jZS92MC4yIiwicHJlZGljYXRlIjp7ImJ1aWxkVHlwZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vY2xpL2doYUB2MSIsImJ1aWxkZXIiOnsiaWQiOiJodHRwczovL2dpdGh1Yi5jb20vbnBtL2NsaUA5LjUuMCJ9LCJpbnZvY2F0aW9uIjp7ImNvbmZpZ1NvdXJjZSI6eyJ1cmkiOiJnaXQraHR0cHM6Ly9naXRodWIuY29tL2xhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QHJlZnMvaGVhZHMvbWFpbiIsImRpZ2VzdCI6eyJzaGExIjoiMTZiYWJmZmI5MTUzODExZTE5M2MwMTk5MzkzOTEzNTczNzJiMjVjZSJ9LCJlbnRyeVBvaW50IjoibGF1cmVudHNpbW9uL3Byb3ZlbmFuY2UtbnBtLXRlc3QvLmdpdGh1Yi93b3JrZmxvd3MvcmVsZWFzZS55bWxAcmVmcy9oZWFkcy9tYWluIn0sInBhcmFtZXRlcnMiOnt9LCJlbnZpcm9ubWVudCI6eyJHSVRIVUJfQUNUT1JfSUQiOiI2NDUwNTA5OSIsIkdJVEhVQl9FVkVOVF9OQU1FIjoid29ya2Zsb3dfZGlzcGF0Y2giLCJHSVRIVUJfUkVGIjoicmVmcy9oZWFkcy9tYWluIiwiR0lUSFVCX1JFRl9UWVBFIjoiYnJhbmNoIiwiR0lUSFVCX1JFUE9TSVRPUlkiOiJsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsIkdJVEhVQl9SRVBPU0lUT1JZX0lEIjoiNjAyMjIzOTQ1IiwiR0lUSFVCX1JFUE9TSVRPUllfT1dORVJfSUQiOiI2NDUwNTA5OSIsIkdJVEhVQl9SVU5fQVRURU1QVCI6IjEiLCJHSVRIVUJfUlVOX0lEIjoiNDE4NzQ2NDU3NyIsIkdJVEhVQl9SVU5fTlVNQkVSIjoiMiIsIkdJVEhVQl9TSEEiOiIxNmJhYmZmYjkxNTM4MTFlMTkzYzAxOTkzOTM5MTM1NzM3MmIyNWNlIiwiR0lUSFVCX1dPUktGTE9XX1JFRiI6ImxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbiIsIkdJVEhVQl9XT1JLRkxPV19TSEEiOiIxNmJhYmZmYjkxNTM4MTFlMTkzYzAxOTkzOTM5MTM1NzM3MmIyNWNlIn19LCJtZXRhZGF0YSI6eyJidWlsZEludm9jYXRpb25JZCI6IjQxODc0NjQ1NzctMSIsImNvbXBsZXRlbmVzcyI6eyJwYXJhbWV0ZXJzIjpmYWxzZSwiZW52aXJvbm1lbnQiOmZhbHNlLCJtYXRlcmlhbHMiOmZhbHNlfSwicmVwcm9kdWNpYmxlIjpmYWxzZX0sIm1hdGVyaWFscyI6W3sidXJpIjoiZ2l0K2h0dHBzOi8vZ2l0aHViLmNvbS9sYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsImRpZ2VzdCI6eyJzaGExIjoiMTZiYWJmZmI5MTUzODExZTE5M2MwMTk5MzkzOTEzNTczNzJiMjVjZSJ9fV19fQ==", + "payloadType": "application/vnd.in-toto+jsonA", + "signatures": [ + { + "sig": "MEUCIQDJahTpSnlv6HzUj2y1/PBYLFy8hhJ+5eABY7uy8RPsGQIgJVuL3Gr9yb2TPUEMs6Iei5HPHbyGl6ixgd41yvy07RQ=", + "keyid": "" + } + ] + } + } + }, + { + "predicateType": "https://github.com/npm/attestation/tree/main/specs/publish/v0.1", + "bundle": { + "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.1", + "verificationMaterial": { + "publicKey": { + "hint": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA" + }, + "tlogEntries": [ + { + "logIndex": "13420289", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "intoto", + "version": "0.0.2" + }, + "integratedTime": "1676489615", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCICYgQbiFj7t0A9B/p4Hkq5H0gB41InPBFFnhEeuP4Fo0AiEA7fGqVACs5cFpoQGHX8HVDq/jKBWbS0gutPXpcOz6r6g=" + }, + "inclusionProof": null, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7ImtleWlkIjoiU0hBMjU2OmpsM2J3c3d1ODBQampva0NnaDBvMnc1YzJVNExoUUFFNTdnajljejFrekEiLCJwdWJsaWNLZXkiOiJMUzB0TFMxQ1JVZEpUaUJRVlVKTVNVTWdTMFZaTFMwdExTMEtUVVpyZDBWM1dVaExiMXBKZW1vd1EwRlJXVWxMYjFwSmVtb3dSRUZSWTBSUlowRkZNVTlzWWpONlRVRkdSbmhZUzBocFNXdFJUelZqU2pOWmFHdzFhVFpWVUhBclNXaDFkR1ZDU21KMVNHTkJOVlZ2WjB0dk1FVlhkR3hYZDFjMlMxTmhTMjlVVGtWWlREZEtiRU5SYVZadWEyaENhM1JWWjJjOVBRb3RMUzB0TFVWT1JDQlFWVUpNU1VNZ1MwVlpMUzB0TFMwPSIsInNpZyI6IlRVVlJRMGxETURGaFJqbFFZVWxtSzNOcVkzRlBiVzQwUVZaVU56bFBWMFJuVkZGVk5XVXZiVkp0TVcweVNIWjVRV2xCY0hCNk1FWkxWVzFEVjJwdVUyUnJORzB5VkdGTlpXMXFSRXRqUlcxTVdFSTRWVVpFTlZsYWRETTJaejA5In1dfSwiaGFzaCI6eyJhbGdvcml0aG0iOiJzaGEyNTYiLCJ2YWx1ZSI6IjkxNDU3YjdiYzg1NTgwY2Y2NTAxNDM5NDU5ZDYyOWI0YzBlOTUxNmFjNzc3NTllNGQwNzMwZjVlMTUxNjRkMDcifSwicGF5bG9hZEhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI1ZmFmZTQwMmJiYzBiMTNhMmFmMmIzMjhjYmNjNmFiZTlmZTA1MGRkNDUzNjNkNTE1YWIyYzk4MjA3NDMwNjVkIn19fX0=" + } + ], + "timestampVerificationData": null + }, + "dsseEnvelope": { + "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInN1YmplY3QiOlt7Im5hbWUiOiJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwiZGlnZXN0Ijp7InNoYTUxMiI6IjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIn19XSwicHJlZGljYXRlVHlwZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsInByZWRpY2F0ZSI6eyJuYW1lIjoiQGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0IiwidmVyc2lvbiI6IjEuMC4wIiwicmVnaXN0cnkiOiJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyJ9fQ==", + "payloadType": "application/vnd.in-toto+json", + "signatures": [ + { + "sig": "MEQCIC01aF9PaIf+sjcqOmn4AVT79OWDgTQU5e/mRm1m2HvyAiAppz0FKUmCWjnSdk4m2TaMemjDKcEmLXB8UFD5YZt36g==", + "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA" + } + ] + } + } + } +] diff --git a/verifiers/internal/gha/testdata/npm-att-mismatch-pub-predicatetype.intoto.sigstore b/verifiers/internal/gha/testdata/npm-att-mismatch-pub-predicatetype.intoto.sigstore new file mode 100644 index 0000000..5d639ce --- /dev/null +++ b/verifiers/internal/gha/testdata/npm-att-mismatch-pub-predicatetype.intoto.sigstore @@ -0,0 +1,92 @@ +[ + { + "predicateType": "https://slsa.dev/provenance/v0.2", + "bundle": { + "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.1", + "verificationMaterial": { + "x509CertificateChain": { + "certificates": [ + { + "rawBytes": "MIIDzTCCA1SgAwIBAgIUSUNeEjOTOlxw2mAmVuog6waz+NcwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjMwMjE1MTkzMzMyWhcNMjMwMjE1MTk0MzMyWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVWrN2Ayc3U80RBnqrFssCXrFETeyMskQhLAXaOAbaPylLa6GiuhrZUEd+i2Q+kvtlOJN6WvJaoIirGUUw84scKOCAnMwggJvMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUgYNyCZHUpkzBfqlfSh2+dV/nqg8wHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wbwYDVR0RAQH/BGUwY4ZhaHR0cHM6Ly9naXRodWIuY29tL2xhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbjA5BgorBgEEAYO/MAEBBCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMB8GCisGAQQBg78wAQIEEXdvcmtmbG93X2Rpc3BhdGNoMDYGCisGAQQBg78wAQMEKDE2YmFiZmZiOTE1MzgxMWUxOTNjMDE5OTM5MzkxMzU3MzcyYjI1Y2UwJgYKKwYBBAGDvzABBAQYUHVibGlzaCBQYWNrYWdlIHRvIG5wbWpzMC4GCisGAQQBg78wAQUEIGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0MB0GCisGAQQBg78wAQYED3JlZnMvaGVhZHMvbWFpbjCBiwYKKwYBBAHWeQIEAgR9BHsAeQB3AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABhlaRXNMAAAQDAEgwRgIhAOZYHC2AyB4Mm5uV6etiegcdoB5t/3Q6e8pah2BH60urAiEAv9rv6WNIyPfXrP1yzykQldw9iExSBh/brNNjTLzP+wYwCgYIKoZIzj0EAwMDZwAwZAIwT+nOUcGmT+K1gtU/ETiJewRTXtX5bjFh0AEDWzVFlLQKk+CMCr+CmhJgfobd83qwAjAz9Wp4/krIgy+qD7oeCwlUH74MNgWpy2QU5Ox3J61wP2/0O7bhH5fDaGtYUFKZzwA=" + }, + { + "rawBytes": "MIICGjCCAaGgAwIBAgIUALnViVfnU0brJasmRkHrn/UnfaQwCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMjA0MTMyMDA2MTVaFw0zMTEwMDUxMzU2NThaMDcxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEeMBwGA1UEAxMVc2lnc3RvcmUtaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8RVS/ysH+NOvuDZyPIZtilgUF9NlarYpAd9HP1vBBH1U5CV77LSS7s0ZiH4nE7Hv7ptS6LvvR/STk798LVgMzLlJ4HeIfF3tHSaexLcYpSASr1kS0N/RgBJz/9jWCiXno3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU39Ppz1YkEZb5qNjpKFWixi4YZD8wHwYDVR0jBBgwFoAUWMAeX5FFpWapesyQoZMi0CrFxfowCgYIKoZIzj0EAwMDZwAwZAIwPCsQK4DYiZYDPIaDi5HFKnfxXx6ASSVmERfsynYBiX2X6SJRnZU84/9DZdnFvvxmAjBOt6QpBlc4J/0DxvkTCqpclvziL6BCCPnjdlIB3Pu3BxsPmygUY7Ii2zbdCdliiow=" + }, + { + "rawBytes": "MIIB9zCCAXygAwIBAgIUALZNAPFdxHPwjeDloDwyYChAO/4wCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMTEwMDcxMzU2NTlaFw0zMTEwMDUxMzU2NThaMCoxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjERMA8GA1UEAxMIc2lnc3RvcmUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT7XeFT4rb3PQGwS4IajtLk3/OlnpgangaBclYpsYBr5i+4ynB07ceb3LP0OIOZdxexX69c5iVuyJRQ+Hz05yi+UF3uBWAlHpiS5sh0+H2GHE7SXrk1EC5m1Tr19L9gg92jYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRYwB5fkUWlZql6zJChkyLQKsXF+jAfBgNVHSMEGDAWgBRYwB5fkUWlZql6zJChkyLQKsXF+jAKBggqhkjOPQQDAwNpADBmAjEAj1nHeXZp+13NWBNa+EDsDP8G1WWg1tCMWP/WHPqpaVo0jhsweNFZgSs0eE7wYI4qAjEA2WB9ot98sIkoF3vZYdd3/VtWB5b9TNMea7Ix/stJ5TfcLLeABLE4BNJOsQ4vnBHJ" + } + ] + }, + "tlogEntries": [ + { + "logIndex": "13420286", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "intoto", + "version": "0.0.2" + }, + "integratedTime": "1676489612", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCIG/LjJ5tqTgKvbA0F+96CJHIk2X0S+9cBz1Z04BfU7dLAiEA7cpf1Agv0VyEu0wR41nEZ9AZ6GVaYR5rf4AAYIZr4hk=" + }, + "inclusionProof": null, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7InB1YmxpY0tleSI6IkxTMHRMUzFDUlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVI2VkVORFFURlRaMEYzU1VKQlowbFZVMVZPWlVWcVQxUlBiSGgzTW0xQmJWWjFiMmMyZDJGNkswNWpkME5uV1VsTGIxcEplbW93UlVGM1RYY0tUbnBGVmsxQ1RVZEJNVlZGUTJoTlRXTXliRzVqTTFKMlkyMVZkVnBIVmpKTlVqUjNTRUZaUkZaUlVVUkZlRlo2WVZka2VtUkhPWGxhVXpGd1ltNVNiQXBqYlRGc1drZHNhR1JIVlhkSWFHTk9UV3BOZDAxcVJURk5WR3Q2VFhwTmVWZG9ZMDVOYWsxM1RXcEZNVTFVYXpCTmVrMTVWMnBCUVUxR2EzZEZkMWxJQ2t0dldrbDZhakJEUVZGWlNVdHZXa2w2YWpCRVFWRmpSRkZuUVVWV1YzSk9Na0Y1WXpOVk9EQlNRbTV4Y2taemMwTllja1pGVkdWNVRYTnJVV2hNUVZnS1lVOUJZbUZRZVd4TVlUWkhhWFZvY2xwVlJXUXJhVEpSSzJ0MmRHeFBTazQyVjNaS1lXOUphWEpIVlZWM09EUnpZMHRQUTBGdVRYZG5aMHAyVFVFMFJ3cEJNVlZrUkhkRlFpOTNVVVZCZDBsSVowUkJWRUpuVGxaSVUxVkZSRVJCUzBKblozSkNaMFZHUWxGalJFRjZRV1JDWjA1V1NGRTBSVVpuVVZWbldVNTVDa05hU0ZWd2EzcENabkZzWmxOb01pdGtWaTl1Y1djNGQwaDNXVVJXVWpCcVFrSm5kMFp2UVZVek9WQndlakZaYTBWYVlqVnhUbXB3UzBaWGFYaHBORmtLV2tRNGQySjNXVVJXVWpCU1FWRklMMEpIVlhkWk5GcG9ZVWhTTUdOSVRUWk1lVGx1WVZoU2IyUlhTWFZaTWpsMFRESjRhR1JZU214aWJsSjZZVmN4ZGdwaWFUbDNZMjA1TWxwWE5XaGliVTVzVEZjMWQySlRNVEJhV0U0d1RIazFibUZZVW05a1YwbDJaREk1ZVdFeVduTmlNMlI2VEROS2JHSkhWbWhqTWxWMUNtVlhNWE5SU0Vwc1dtNU5kbUZIVm1oYVNFMTJZbGRHY0dKcVFUVkNaMjl5UW1kRlJVRlpUeTlOUVVWQ1FrTjBiMlJJVW5kamVtOTJURE5TZG1FeVZuVUtURzFHYW1SSGJIWmliazExV2pKc01HRklWbWxrV0U1c1kyMU9kbUp1VW14aWJsRjFXVEk1ZEUxQ09FZERhWE5IUVZGUlFtYzNPSGRCVVVsRlJWaGtkZ3BqYlhSdFlrYzVNMWd5VW5Cak0wSm9aRWRPYjAxRVdVZERhWE5IUVZGUlFtYzNPSGRCVVUxRlMwUkZNbGx0Um1sYWJWcHBUMVJGTVUxNlozaE5WMVY0Q2s5VVRtcE5SRVUxVDFSTk5VMTZhM2hOZWxVelRYcGplVmxxU1RGWk1sVjNTbWRaUzB0M1dVSkNRVWRFZG5wQlFrSkJVVmxWU0ZacFlrZHNlbUZEUWxFS1dWZE9jbGxYWkd4SlNGSjJTVWMxZDJKWGNIcE5RelJIUTJselIwRlJVVUpuTnpoM1FWRlZSVWxIZUdoa1dFcHNZbTVTZW1GWE1YWmlhVGwzWTIwNU1ncGFWelZvWW0xT2JFeFhOWGRpVXpFd1dsaE9NRTFDTUVkRGFYTkhRVkZSUW1jM09IZEJVVmxGUkROS2JGcHVUWFpoUjFab1draE5kbUpYUm5CaWFrTkNDbWwzV1V0TGQxbENRa0ZJVjJWUlNVVkJaMUk1UWtoelFXVlJRak5CVGpBNVRVZHlSM2g0UlhsWmVHdGxTRXBzYms1M1MybFRiRFkwTTJwNWRDODBaVXNLWTI5QmRrdGxOazlCUVVGQ2FHeGhVbGhPVFVGQlFWRkVRVVZuZDFKblNXaEJUMXBaU0VNeVFYbENORTF0TlhWV05tVjBhV1ZuWTJSdlFqVjBMek5STmdwbE9IQmhhREpDU0RZd2RYSkJhVVZCZGpseWRqWlhUa2w1VUdaWWNsQXhlWHA1YTFGc1pIYzVhVVY0VTBKb0wySnlUazVxVkV4NlVDdDNXWGREWjFsSkNrdHZXa2w2YWpCRlFYZE5SRnAzUVhkYVFVbDNWQ3R1VDFWalIyMVVLMHN4WjNSVkwwVlVhVXBsZDFKVVdIUllOV0pxUm1nd1FVVkVWM3BXUm14TVVVc0theXREVFVOeUswTnRhRXBuWm05aVpEZ3pjWGRCYWtGNk9WZHdOQzlyY2tsbmVTdHhSRGR2WlVOM2JGVklOelJOVG1kWGNIa3lVVlUxVDNnelNqWXhkd3BRTWk4d1R6ZGlhRWcxWmtSaFIzUlpWVVpMV25wM1FUMEtMUzB0TFMxRlRrUWdRMFZTVkVsR1NVTkJWRVV0TFMwdExRbz0iLCJzaWciOiJUVVZWUTBsUlJFcGhhRlJ3VTI1c2RqWkllbFZxTW5reEwxQkNXVXhHZVRob2FFb3JOV1ZCUWxrM2RYazRVbEJ6UjFGSlowcFdkVXd6UjNJNWVXSXlWRkJWUlUxek5rbGxhVFZJVUVoaWVVZHNObWw0WjJRME1YbDJlVEEzVWxFOSJ9XX0sImhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIyYzVhZjNiZThjNzcxYzAwYzVhZGYwNDAxMzQ5YTg1NjM5NjA3Nzg4MzQwNjRhMmYyOTk5YzY4YmZiMWI0Njg4In0sInBheWxvYWRIYXNoIjp7ImFsZ29yaXRobSI6InNoYTI1NiIsInZhbHVlIjoiNjg5ZTE2NmNlM2I1Zjk5MTgxZDExYjcyYjg2OTJkODEwYjJlM2NkMTdmZWNiZjBiNzRmNDBmYTRmNmUzNjNkNSJ9fX19" + } + ], + "timestampVerificationData": null + }, + "dsseEnvelope": { + "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInN1YmplY3QiOlt7Im5hbWUiOiJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwiZGlnZXN0Ijp7InNoYTUxMiI6IjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIn19XSwicHJlZGljYXRlVHlwZSI6Imh0dHBzOi8vc2xzYS5kZXYvcHJvdmVuYW5jZS92MC4yIiwicHJlZGljYXRlIjp7ImJ1aWxkVHlwZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vY2xpL2doYUB2MSIsImJ1aWxkZXIiOnsiaWQiOiJodHRwczovL2dpdGh1Yi5jb20vbnBtL2NsaUA5LjUuMCJ9LCJpbnZvY2F0aW9uIjp7ImNvbmZpZ1NvdXJjZSI6eyJ1cmkiOiJnaXQraHR0cHM6Ly9naXRodWIuY29tL2xhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QHJlZnMvaGVhZHMvbWFpbiIsImRpZ2VzdCI6eyJzaGExIjoiMTZiYWJmZmI5MTUzODExZTE5M2MwMTk5MzkzOTEzNTczNzJiMjVjZSJ9LCJlbnRyeVBvaW50IjoibGF1cmVudHNpbW9uL3Byb3ZlbmFuY2UtbnBtLXRlc3QvLmdpdGh1Yi93b3JrZmxvd3MvcmVsZWFzZS55bWxAcmVmcy9oZWFkcy9tYWluIn0sInBhcmFtZXRlcnMiOnt9LCJlbnZpcm9ubWVudCI6eyJHSVRIVUJfQUNUT1JfSUQiOiI2NDUwNTA5OSIsIkdJVEhVQl9FVkVOVF9OQU1FIjoid29ya2Zsb3dfZGlzcGF0Y2giLCJHSVRIVUJfUkVGIjoicmVmcy9oZWFkcy9tYWluIiwiR0lUSFVCX1JFRl9UWVBFIjoiYnJhbmNoIiwiR0lUSFVCX1JFUE9TSVRPUlkiOiJsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsIkdJVEhVQl9SRVBPU0lUT1JZX0lEIjoiNjAyMjIzOTQ1IiwiR0lUSFVCX1JFUE9TSVRPUllfT1dORVJfSUQiOiI2NDUwNTA5OSIsIkdJVEhVQl9SVU5fQVRURU1QVCI6IjEiLCJHSVRIVUJfUlVOX0lEIjoiNDE4NzQ2NDU3NyIsIkdJVEhVQl9SVU5fTlVNQkVSIjoiMiIsIkdJVEhVQl9TSEEiOiIxNmJhYmZmYjkxNTM4MTFlMTkzYzAxOTkzOTM5MTM1NzM3MmIyNWNlIiwiR0lUSFVCX1dPUktGTE9XX1JFRiI6ImxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbiIsIkdJVEhVQl9XT1JLRkxPV19TSEEiOiIxNmJhYmZmYjkxNTM4MTFlMTkzYzAxOTkzOTM5MTM1NzM3MmIyNWNlIn19LCJtZXRhZGF0YSI6eyJidWlsZEludm9jYXRpb25JZCI6IjQxODc0NjQ1NzctMSIsImNvbXBsZXRlbmVzcyI6eyJwYXJhbWV0ZXJzIjpmYWxzZSwiZW52aXJvbm1lbnQiOmZhbHNlLCJtYXRlcmlhbHMiOmZhbHNlfSwicmVwcm9kdWNpYmxlIjpmYWxzZX0sIm1hdGVyaWFscyI6W3sidXJpIjoiZ2l0K2h0dHBzOi8vZ2l0aHViLmNvbS9sYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsImRpZ2VzdCI6eyJzaGExIjoiMTZiYWJmZmI5MTUzODExZTE5M2MwMTk5MzkzOTEzNTczNzJiMjVjZSJ9fV19fQ==", + "payloadType": "application/vnd.in-toto+json", + "signatures": [ + { + "sig": "MEUCIQDJahTpSnlv6HzUj2y1/PBYLFy8hhJ+5eABY7uy8RPsGQIgJVuL3Gr9yb2TPUEMs6Iei5HPHbyGl6ixgd41yvy07RQ=", + "keyid": "" + } + ] + } + } + }, + { + "predicateType": "https://github.com/npm/attestation/tree/main/specs/publis/v0.1", + "bundle": { + "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.1", + "verificationMaterial": { + "publicKey": { + "hint": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA" + }, + "tlogEntries": [ + { + "logIndex": "13420289", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "intoto", + "version": "0.0.2" + }, + "integratedTime": "1676489615", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCICYgQbiFj7t0A9B/p4Hkq5H0gB41InPBFFnhEeuP4Fo0AiEA7fGqVACs5cFpoQGHX8HVDq/jKBWbS0gutPXpcOz6r6g=" + }, + "inclusionProof": null, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7ImtleWlkIjoiU0hBMjU2OmpsM2J3c3d1ODBQampva0NnaDBvMnc1YzJVNExoUUFFNTdnajljejFrekEiLCJwdWJsaWNLZXkiOiJMUzB0TFMxQ1JVZEpUaUJRVlVKTVNVTWdTMFZaTFMwdExTMEtUVVpyZDBWM1dVaExiMXBKZW1vd1EwRlJXVWxMYjFwSmVtb3dSRUZSWTBSUlowRkZNVTlzWWpONlRVRkdSbmhZUzBocFNXdFJUelZqU2pOWmFHdzFhVFpWVUhBclNXaDFkR1ZDU21KMVNHTkJOVlZ2WjB0dk1FVlhkR3hYZDFjMlMxTmhTMjlVVGtWWlREZEtiRU5SYVZadWEyaENhM1JWWjJjOVBRb3RMUzB0TFVWT1JDQlFWVUpNU1VNZ1MwVlpMUzB0TFMwPSIsInNpZyI6IlRVVlJRMGxETURGaFJqbFFZVWxtSzNOcVkzRlBiVzQwUVZaVU56bFBWMFJuVkZGVk5XVXZiVkp0TVcweVNIWjVRV2xCY0hCNk1FWkxWVzFEVjJwdVUyUnJORzB5VkdGTlpXMXFSRXRqUlcxTVdFSTRWVVpFTlZsYWRETTJaejA5In1dfSwiaGFzaCI6eyJhbGdvcml0aG0iOiJzaGEyNTYiLCJ2YWx1ZSI6IjkxNDU3YjdiYzg1NTgwY2Y2NTAxNDM5NDU5ZDYyOWI0YzBlOTUxNmFjNzc3NTllNGQwNzMwZjVlMTUxNjRkMDcifSwicGF5bG9hZEhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI1ZmFmZTQwMmJiYzBiMTNhMmFmMmIzMjhjYmNjNmFiZTlmZTA1MGRkNDUzNjNkNTE1YWIyYzk4MjA3NDMwNjVkIn19fX0=" + } + ], + "timestampVerificationData": null + }, + "dsseEnvelope": { + "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInN1YmplY3QiOlt7Im5hbWUiOiJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwiZGlnZXN0Ijp7InNoYTUxMiI6IjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIn19XSwicHJlZGljYXRlVHlwZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsInByZWRpY2F0ZSI6eyJuYW1lIjoiQGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0IiwidmVyc2lvbiI6IjEuMC4wIiwicmVnaXN0cnkiOiJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyJ9fQ==", + "payloadType": "application/vnd.in-toto+json", + "signatures": [ + { + "sig": "MEQCIC01aF9PaIf+sjcqOmn4AVT79OWDgTQU5e/mRm1m2HvyAiAppz0FKUmCWjnSdk4m2TaMemjDKcEmLXB8UFD5YZt36g==", + "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA" + } + ] + } + } + } +] diff --git a/verifiers/internal/gha/testdata/npm-attestations.intoto.sigstore b/verifiers/internal/gha/testdata/npm-attestations.intoto.sigstore new file mode 100644 index 0000000..5b7b6c9 --- /dev/null +++ b/verifiers/internal/gha/testdata/npm-attestations.intoto.sigstore @@ -0,0 +1,92 @@ +[ + { + "predicateType": "https://slsa.dev/provenance/v0.2", + "bundle": { + "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.1", + "verificationMaterial": { + "x509CertificateChain": { + "certificates": [ + { + "rawBytes": "MIIDzTCCA1SgAwIBAgIUSUNeEjOTOlxw2mAmVuog6waz+NcwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjMwMjE1MTkzMzMyWhcNMjMwMjE1MTk0MzMyWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVWrN2Ayc3U80RBnqrFssCXrFETeyMskQhLAXaOAbaPylLa6GiuhrZUEd+i2Q+kvtlOJN6WvJaoIirGUUw84scKOCAnMwggJvMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUgYNyCZHUpkzBfqlfSh2+dV/nqg8wHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wbwYDVR0RAQH/BGUwY4ZhaHR0cHM6Ly9naXRodWIuY29tL2xhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbjA5BgorBgEEAYO/MAEBBCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMB8GCisGAQQBg78wAQIEEXdvcmtmbG93X2Rpc3BhdGNoMDYGCisGAQQBg78wAQMEKDE2YmFiZmZiOTE1MzgxMWUxOTNjMDE5OTM5MzkxMzU3MzcyYjI1Y2UwJgYKKwYBBAGDvzABBAQYUHVibGlzaCBQYWNrYWdlIHRvIG5wbWpzMC4GCisGAQQBg78wAQUEIGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0MB0GCisGAQQBg78wAQYED3JlZnMvaGVhZHMvbWFpbjCBiwYKKwYBBAHWeQIEAgR9BHsAeQB3AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABhlaRXNMAAAQDAEgwRgIhAOZYHC2AyB4Mm5uV6etiegcdoB5t/3Q6e8pah2BH60urAiEAv9rv6WNIyPfXrP1yzykQldw9iExSBh/brNNjTLzP+wYwCgYIKoZIzj0EAwMDZwAwZAIwT+nOUcGmT+K1gtU/ETiJewRTXtX5bjFh0AEDWzVFlLQKk+CMCr+CmhJgfobd83qwAjAz9Wp4/krIgy+qD7oeCwlUH74MNgWpy2QU5Ox3J61wP2/0O7bhH5fDaGtYUFKZzwA=" + }, + { + "rawBytes": "MIICGjCCAaGgAwIBAgIUALnViVfnU0brJasmRkHrn/UnfaQwCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMjA0MTMyMDA2MTVaFw0zMTEwMDUxMzU2NThaMDcxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEeMBwGA1UEAxMVc2lnc3RvcmUtaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8RVS/ysH+NOvuDZyPIZtilgUF9NlarYpAd9HP1vBBH1U5CV77LSS7s0ZiH4nE7Hv7ptS6LvvR/STk798LVgMzLlJ4HeIfF3tHSaexLcYpSASr1kS0N/RgBJz/9jWCiXno3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU39Ppz1YkEZb5qNjpKFWixi4YZD8wHwYDVR0jBBgwFoAUWMAeX5FFpWapesyQoZMi0CrFxfowCgYIKoZIzj0EAwMDZwAwZAIwPCsQK4DYiZYDPIaDi5HFKnfxXx6ASSVmERfsynYBiX2X6SJRnZU84/9DZdnFvvxmAjBOt6QpBlc4J/0DxvkTCqpclvziL6BCCPnjdlIB3Pu3BxsPmygUY7Ii2zbdCdliiow=" + }, + { + "rawBytes": "MIIB9zCCAXygAwIBAgIUALZNAPFdxHPwjeDloDwyYChAO/4wCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMTEwMDcxMzU2NTlaFw0zMTEwMDUxMzU2NThaMCoxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjERMA8GA1UEAxMIc2lnc3RvcmUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT7XeFT4rb3PQGwS4IajtLk3/OlnpgangaBclYpsYBr5i+4ynB07ceb3LP0OIOZdxexX69c5iVuyJRQ+Hz05yi+UF3uBWAlHpiS5sh0+H2GHE7SXrk1EC5m1Tr19L9gg92jYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRYwB5fkUWlZql6zJChkyLQKsXF+jAfBgNVHSMEGDAWgBRYwB5fkUWlZql6zJChkyLQKsXF+jAKBggqhkjOPQQDAwNpADBmAjEAj1nHeXZp+13NWBNa+EDsDP8G1WWg1tCMWP/WHPqpaVo0jhsweNFZgSs0eE7wYI4qAjEA2WB9ot98sIkoF3vZYdd3/VtWB5b9TNMea7Ix/stJ5TfcLLeABLE4BNJOsQ4vnBHJ" + } + ] + }, + "tlogEntries": [ + { + "logIndex": "13420286", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "intoto", + "version": "0.0.2" + }, + "integratedTime": "1676489612", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCIG/LjJ5tqTgKvbA0F+96CJHIk2X0S+9cBz1Z04BfU7dLAiEA7cpf1Agv0VyEu0wR41nEZ9AZ6GVaYR5rf4AAYIZr4hk=" + }, + "inclusionProof": null, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7InB1YmxpY0tleSI6IkxTMHRMUzFDUlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVI2VkVORFFURlRaMEYzU1VKQlowbFZVMVZPWlVWcVQxUlBiSGgzTW0xQmJWWjFiMmMyZDJGNkswNWpkME5uV1VsTGIxcEplbW93UlVGM1RYY0tUbnBGVmsxQ1RVZEJNVlZGUTJoTlRXTXliRzVqTTFKMlkyMVZkVnBIVmpKTlVqUjNTRUZaUkZaUlVVUkZlRlo2WVZka2VtUkhPWGxhVXpGd1ltNVNiQXBqYlRGc1drZHNhR1JIVlhkSWFHTk9UV3BOZDAxcVJURk5WR3Q2VFhwTmVWZG9ZMDVOYWsxM1RXcEZNVTFVYXpCTmVrMTVWMnBCUVUxR2EzZEZkMWxJQ2t0dldrbDZhakJEUVZGWlNVdHZXa2w2YWpCRVFWRmpSRkZuUVVWV1YzSk9Na0Y1WXpOVk9EQlNRbTV4Y2taemMwTllja1pGVkdWNVRYTnJVV2hNUVZnS1lVOUJZbUZRZVd4TVlUWkhhWFZvY2xwVlJXUXJhVEpSSzJ0MmRHeFBTazQyVjNaS1lXOUphWEpIVlZWM09EUnpZMHRQUTBGdVRYZG5aMHAyVFVFMFJ3cEJNVlZrUkhkRlFpOTNVVVZCZDBsSVowUkJWRUpuVGxaSVUxVkZSRVJCUzBKblozSkNaMFZHUWxGalJFRjZRV1JDWjA1V1NGRTBSVVpuVVZWbldVNTVDa05hU0ZWd2EzcENabkZzWmxOb01pdGtWaTl1Y1djNGQwaDNXVVJXVWpCcVFrSm5kMFp2UVZVek9WQndlakZaYTBWYVlqVnhUbXB3UzBaWGFYaHBORmtLV2tRNGQySjNXVVJXVWpCU1FWRklMMEpIVlhkWk5GcG9ZVWhTTUdOSVRUWk1lVGx1WVZoU2IyUlhTWFZaTWpsMFRESjRhR1JZU214aWJsSjZZVmN4ZGdwaWFUbDNZMjA1TWxwWE5XaGliVTVzVEZjMWQySlRNVEJhV0U0d1RIazFibUZZVW05a1YwbDJaREk1ZVdFeVduTmlNMlI2VEROS2JHSkhWbWhqTWxWMUNtVlhNWE5SU0Vwc1dtNU5kbUZIVm1oYVNFMTJZbGRHY0dKcVFUVkNaMjl5UW1kRlJVRlpUeTlOUVVWQ1FrTjBiMlJJVW5kamVtOTJURE5TZG1FeVZuVUtURzFHYW1SSGJIWmliazExV2pKc01HRklWbWxrV0U1c1kyMU9kbUp1VW14aWJsRjFXVEk1ZEUxQ09FZERhWE5IUVZGUlFtYzNPSGRCVVVsRlJWaGtkZ3BqYlhSdFlrYzVNMWd5VW5Cak0wSm9aRWRPYjAxRVdVZERhWE5IUVZGUlFtYzNPSGRCVVUxRlMwUkZNbGx0Um1sYWJWcHBUMVJGTVUxNlozaE5WMVY0Q2s5VVRtcE5SRVUxVDFSTk5VMTZhM2hOZWxVelRYcGplVmxxU1RGWk1sVjNTbWRaUzB0M1dVSkNRVWRFZG5wQlFrSkJVVmxWU0ZacFlrZHNlbUZEUWxFS1dWZE9jbGxYWkd4SlNGSjJTVWMxZDJKWGNIcE5RelJIUTJselIwRlJVVUpuTnpoM1FWRlZSVWxIZUdoa1dFcHNZbTVTZW1GWE1YWmlhVGwzWTIwNU1ncGFWelZvWW0xT2JFeFhOWGRpVXpFd1dsaE9NRTFDTUVkRGFYTkhRVkZSUW1jM09IZEJVVmxGUkROS2JGcHVUWFpoUjFab1draE5kbUpYUm5CaWFrTkNDbWwzV1V0TGQxbENRa0ZJVjJWUlNVVkJaMUk1UWtoelFXVlJRak5CVGpBNVRVZHlSM2g0UlhsWmVHdGxTRXBzYms1M1MybFRiRFkwTTJwNWRDODBaVXNLWTI5QmRrdGxOazlCUVVGQ2FHeGhVbGhPVFVGQlFWRkVRVVZuZDFKblNXaEJUMXBaU0VNeVFYbENORTF0TlhWV05tVjBhV1ZuWTJSdlFqVjBMek5STmdwbE9IQmhhREpDU0RZd2RYSkJhVVZCZGpseWRqWlhUa2w1VUdaWWNsQXhlWHA1YTFGc1pIYzVhVVY0VTBKb0wySnlUazVxVkV4NlVDdDNXWGREWjFsSkNrdHZXa2w2YWpCRlFYZE5SRnAzUVhkYVFVbDNWQ3R1VDFWalIyMVVLMHN4WjNSVkwwVlVhVXBsZDFKVVdIUllOV0pxUm1nd1FVVkVWM3BXUm14TVVVc0theXREVFVOeUswTnRhRXBuWm05aVpEZ3pjWGRCYWtGNk9WZHdOQzlyY2tsbmVTdHhSRGR2WlVOM2JGVklOelJOVG1kWGNIa3lVVlUxVDNnelNqWXhkd3BRTWk4d1R6ZGlhRWcxWmtSaFIzUlpWVVpMV25wM1FUMEtMUzB0TFMxRlRrUWdRMFZTVkVsR1NVTkJWRVV0TFMwdExRbz0iLCJzaWciOiJUVVZWUTBsUlJFcGhhRlJ3VTI1c2RqWkllbFZxTW5reEwxQkNXVXhHZVRob2FFb3JOV1ZCUWxrM2RYazRVbEJ6UjFGSlowcFdkVXd6UjNJNWVXSXlWRkJWUlUxek5rbGxhVFZJVUVoaWVVZHNObWw0WjJRME1YbDJlVEEzVWxFOSJ9XX0sImhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIyYzVhZjNiZThjNzcxYzAwYzVhZGYwNDAxMzQ5YTg1NjM5NjA3Nzg4MzQwNjRhMmYyOTk5YzY4YmZiMWI0Njg4In0sInBheWxvYWRIYXNoIjp7ImFsZ29yaXRobSI6InNoYTI1NiIsInZhbHVlIjoiNjg5ZTE2NmNlM2I1Zjk5MTgxZDExYjcyYjg2OTJkODEwYjJlM2NkMTdmZWNiZjBiNzRmNDBmYTRmNmUzNjNkNSJ9fX19" + } + ], + "timestampVerificationData": null + }, + "dsseEnvelope": { + "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInN1YmplY3QiOlt7Im5hbWUiOiJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwiZGlnZXN0Ijp7InNoYTUxMiI6IjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIn19XSwicHJlZGljYXRlVHlwZSI6Imh0dHBzOi8vc2xzYS5kZXYvcHJvdmVuYW5jZS92MC4yIiwicHJlZGljYXRlIjp7ImJ1aWxkVHlwZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vY2xpL2doYUB2MSIsImJ1aWxkZXIiOnsiaWQiOiJodHRwczovL2dpdGh1Yi5jb20vbnBtL2NsaUA5LjUuMCJ9LCJpbnZvY2F0aW9uIjp7ImNvbmZpZ1NvdXJjZSI6eyJ1cmkiOiJnaXQraHR0cHM6Ly9naXRodWIuY29tL2xhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QHJlZnMvaGVhZHMvbWFpbiIsImRpZ2VzdCI6eyJzaGExIjoiMTZiYWJmZmI5MTUzODExZTE5M2MwMTk5MzkzOTEzNTczNzJiMjVjZSJ9LCJlbnRyeVBvaW50IjoibGF1cmVudHNpbW9uL3Byb3ZlbmFuY2UtbnBtLXRlc3QvLmdpdGh1Yi93b3JrZmxvd3MvcmVsZWFzZS55bWxAcmVmcy9oZWFkcy9tYWluIn0sInBhcmFtZXRlcnMiOnt9LCJlbnZpcm9ubWVudCI6eyJHSVRIVUJfQUNUT1JfSUQiOiI2NDUwNTA5OSIsIkdJVEhVQl9FVkVOVF9OQU1FIjoid29ya2Zsb3dfZGlzcGF0Y2giLCJHSVRIVUJfUkVGIjoicmVmcy9oZWFkcy9tYWluIiwiR0lUSFVCX1JFRl9UWVBFIjoiYnJhbmNoIiwiR0lUSFVCX1JFUE9TSVRPUlkiOiJsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsIkdJVEhVQl9SRVBPU0lUT1JZX0lEIjoiNjAyMjIzOTQ1IiwiR0lUSFVCX1JFUE9TSVRPUllfT1dORVJfSUQiOiI2NDUwNTA5OSIsIkdJVEhVQl9SVU5fQVRURU1QVCI6IjEiLCJHSVRIVUJfUlVOX0lEIjoiNDE4NzQ2NDU3NyIsIkdJVEhVQl9SVU5fTlVNQkVSIjoiMiIsIkdJVEhVQl9TSEEiOiIxNmJhYmZmYjkxNTM4MTFlMTkzYzAxOTkzOTM5MTM1NzM3MmIyNWNlIiwiR0lUSFVCX1dPUktGTE9XX1JFRiI6ImxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbiIsIkdJVEhVQl9XT1JLRkxPV19TSEEiOiIxNmJhYmZmYjkxNTM4MTFlMTkzYzAxOTkzOTM5MTM1NzM3MmIyNWNlIn19LCJtZXRhZGF0YSI6eyJidWlsZEludm9jYXRpb25JZCI6IjQxODc0NjQ1NzctMSIsImNvbXBsZXRlbmVzcyI6eyJwYXJhbWV0ZXJzIjpmYWxzZSwiZW52aXJvbm1lbnQiOmZhbHNlLCJtYXRlcmlhbHMiOmZhbHNlfSwicmVwcm9kdWNpYmxlIjpmYWxzZX0sIm1hdGVyaWFscyI6W3sidXJpIjoiZ2l0K2h0dHBzOi8vZ2l0aHViLmNvbS9sYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsImRpZ2VzdCI6eyJzaGExIjoiMTZiYWJmZmI5MTUzODExZTE5M2MwMTk5MzkzOTEzNTczNzJiMjVjZSJ9fV19fQ==", + "payloadType": "application/vnd.in-toto+json", + "signatures": [ + { + "sig": "MEUCIQDJahTpSnlv6HzUj2y1/PBYLFy8hhJ+5eABY7uy8RPsGQIgJVuL3Gr9yb2TPUEMs6Iei5HPHbyGl6ixgd41yvy07RQ=", + "keyid": "" + } + ] + } + } + }, + { + "predicateType": "https://github.com/npm/attestation/tree/main/specs/publish/v0.1", + "bundle": { + "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.1", + "verificationMaterial": { + "publicKey": { + "hint": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA" + }, + "tlogEntries": [ + { + "logIndex": "13420289", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "intoto", + "version": "0.0.2" + }, + "integratedTime": "1676489615", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCICYgQbiFj7t0A9B/p4Hkq5H0gB41InPBFFnhEeuP4Fo0AiEA7fGqVACs5cFpoQGHX8HVDq/jKBWbS0gutPXpcOz6r6g=" + }, + "inclusionProof": null, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7ImtleWlkIjoiU0hBMjU2OmpsM2J3c3d1ODBQampva0NnaDBvMnc1YzJVNExoUUFFNTdnajljejFrekEiLCJwdWJsaWNLZXkiOiJMUzB0TFMxQ1JVZEpUaUJRVlVKTVNVTWdTMFZaTFMwdExTMEtUVVpyZDBWM1dVaExiMXBKZW1vd1EwRlJXVWxMYjFwSmVtb3dSRUZSWTBSUlowRkZNVTlzWWpONlRVRkdSbmhZUzBocFNXdFJUelZqU2pOWmFHdzFhVFpWVUhBclNXaDFkR1ZDU21KMVNHTkJOVlZ2WjB0dk1FVlhkR3hYZDFjMlMxTmhTMjlVVGtWWlREZEtiRU5SYVZadWEyaENhM1JWWjJjOVBRb3RMUzB0TFVWT1JDQlFWVUpNU1VNZ1MwVlpMUzB0TFMwPSIsInNpZyI6IlRVVlJRMGxETURGaFJqbFFZVWxtSzNOcVkzRlBiVzQwUVZaVU56bFBWMFJuVkZGVk5XVXZiVkp0TVcweVNIWjVRV2xCY0hCNk1FWkxWVzFEVjJwdVUyUnJORzB5VkdGTlpXMXFSRXRqUlcxTVdFSTRWVVpFTlZsYWRETTJaejA5In1dfSwiaGFzaCI6eyJhbGdvcml0aG0iOiJzaGEyNTYiLCJ2YWx1ZSI6IjkxNDU3YjdiYzg1NTgwY2Y2NTAxNDM5NDU5ZDYyOWI0YzBlOTUxNmFjNzc3NTllNGQwNzMwZjVlMTUxNjRkMDcifSwicGF5bG9hZEhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI1ZmFmZTQwMmJiYzBiMTNhMmFmMmIzMjhjYmNjNmFiZTlmZTA1MGRkNDUzNjNkNTE1YWIyYzk4MjA3NDMwNjVkIn19fX0=" + } + ], + "timestampVerificationData": null + }, + "dsseEnvelope": { + "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInN1YmplY3QiOlt7Im5hbWUiOiJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwiZGlnZXN0Ijp7InNoYTUxMiI6IjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIn19XSwicHJlZGljYXRlVHlwZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsInByZWRpY2F0ZSI6eyJuYW1lIjoiQGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0IiwidmVyc2lvbiI6IjEuMC4wIiwicmVnaXN0cnkiOiJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyJ9fQ==", + "payloadType": "application/vnd.in-toto+json", + "signatures": [ + { + "sig": "MEQCIC01aF9PaIf+sjcqOmn4AVT79OWDgTQU5e/mRm1m2HvyAiAppz0FKUmCWjnSdk4m2TaMemjDKcEmLXB8UFD5YZt36g==", + "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA" + } + ] + } + } + } +] diff --git a/verifiers/internal/gha/testdata/npm-stmt-mismatch-prov-predicatetype.intoto.sigstore b/verifiers/internal/gha/testdata/npm-stmt-mismatch-prov-predicatetype.intoto.sigstore new file mode 100644 index 0000000..9b840ed --- /dev/null +++ b/verifiers/internal/gha/testdata/npm-stmt-mismatch-prov-predicatetype.intoto.sigstore @@ -0,0 +1,92 @@ +[ + { + "predicateType": "https://slsa.dev/provenance/v0.2", + "bundle": { + "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.1", + "verificationMaterial": { + "x509CertificateChain": { + "certificates": [ + { + "rawBytes": "MIIDzTCCA1SgAwIBAgIUSUNeEjOTOlxw2mAmVuog6waz+NcwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjMwMjE1MTkzMzMyWhcNMjMwMjE1MTk0MzMyWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVWrN2Ayc3U80RBnqrFssCXrFETeyMskQhLAXaOAbaPylLa6GiuhrZUEd+i2Q+kvtlOJN6WvJaoIirGUUw84scKOCAnMwggJvMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUgYNyCZHUpkzBfqlfSh2+dV/nqg8wHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wbwYDVR0RAQH/BGUwY4ZhaHR0cHM6Ly9naXRodWIuY29tL2xhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbjA5BgorBgEEAYO/MAEBBCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMB8GCisGAQQBg78wAQIEEXdvcmtmbG93X2Rpc3BhdGNoMDYGCisGAQQBg78wAQMEKDE2YmFiZmZiOTE1MzgxMWUxOTNjMDE5OTM5MzkxMzU3MzcyYjI1Y2UwJgYKKwYBBAGDvzABBAQYUHVibGlzaCBQYWNrYWdlIHRvIG5wbWpzMC4GCisGAQQBg78wAQUEIGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0MB0GCisGAQQBg78wAQYED3JlZnMvaGVhZHMvbWFpbjCBiwYKKwYBBAHWeQIEAgR9BHsAeQB3AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABhlaRXNMAAAQDAEgwRgIhAOZYHC2AyB4Mm5uV6etiegcdoB5t/3Q6e8pah2BH60urAiEAv9rv6WNIyPfXrP1yzykQldw9iExSBh/brNNjTLzP+wYwCgYIKoZIzj0EAwMDZwAwZAIwT+nOUcGmT+K1gtU/ETiJewRTXtX5bjFh0AEDWzVFlLQKk+CMCr+CmhJgfobd83qwAjAz9Wp4/krIgy+qD7oeCwlUH74MNgWpy2QU5Ox3J61wP2/0O7bhH5fDaGtYUFKZzwA=" + }, + { + "rawBytes": "MIICGjCCAaGgAwIBAgIUALnViVfnU0brJasmRkHrn/UnfaQwCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMjA0MTMyMDA2MTVaFw0zMTEwMDUxMzU2NThaMDcxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEeMBwGA1UEAxMVc2lnc3RvcmUtaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8RVS/ysH+NOvuDZyPIZtilgUF9NlarYpAd9HP1vBBH1U5CV77LSS7s0ZiH4nE7Hv7ptS6LvvR/STk798LVgMzLlJ4HeIfF3tHSaexLcYpSASr1kS0N/RgBJz/9jWCiXno3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU39Ppz1YkEZb5qNjpKFWixi4YZD8wHwYDVR0jBBgwFoAUWMAeX5FFpWapesyQoZMi0CrFxfowCgYIKoZIzj0EAwMDZwAwZAIwPCsQK4DYiZYDPIaDi5HFKnfxXx6ASSVmERfsynYBiX2X6SJRnZU84/9DZdnFvvxmAjBOt6QpBlc4J/0DxvkTCqpclvziL6BCCPnjdlIB3Pu3BxsPmygUY7Ii2zbdCdliiow=" + }, + { + "rawBytes": "MIIB9zCCAXygAwIBAgIUALZNAPFdxHPwjeDloDwyYChAO/4wCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMTEwMDcxMzU2NTlaFw0zMTEwMDUxMzU2NThaMCoxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjERMA8GA1UEAxMIc2lnc3RvcmUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT7XeFT4rb3PQGwS4IajtLk3/OlnpgangaBclYpsYBr5i+4ynB07ceb3LP0OIOZdxexX69c5iVuyJRQ+Hz05yi+UF3uBWAlHpiS5sh0+H2GHE7SXrk1EC5m1Tr19L9gg92jYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRYwB5fkUWlZql6zJChkyLQKsXF+jAfBgNVHSMEGDAWgBRYwB5fkUWlZql6zJChkyLQKsXF+jAKBggqhkjOPQQDAwNpADBmAjEAj1nHeXZp+13NWBNa+EDsDP8G1WWg1tCMWP/WHPqpaVo0jhsweNFZgSs0eE7wYI4qAjEA2WB9ot98sIkoF3vZYdd3/VtWB5b9TNMea7Ix/stJ5TfcLLeABLE4BNJOsQ4vnBHJ" + } + ] + }, + "tlogEntries": [ + { + "logIndex": "13420286", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "intoto", + "version": "0.0.2" + }, + "integratedTime": "1676489612", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCIG/LjJ5tqTgKvbA0F+96CJHIk2X0S+9cBz1Z04BfU7dLAiEA7cpf1Agv0VyEu0wR41nEZ9AZ6GVaYR5rf4AAYIZr4hk=" + }, + "inclusionProof": null, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7InB1YmxpY0tleSI6IkxTMHRMUzFDUlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVI2VkVORFFURlRaMEYzU1VKQlowbFZVMVZPWlVWcVQxUlBiSGgzTW0xQmJWWjFiMmMyZDJGNkswNWpkME5uV1VsTGIxcEplbW93UlVGM1RYY0tUbnBGVmsxQ1RVZEJNVlZGUTJoTlRXTXliRzVqTTFKMlkyMVZkVnBIVmpKTlVqUjNTRUZaUkZaUlVVUkZlRlo2WVZka2VtUkhPWGxhVXpGd1ltNVNiQXBqYlRGc1drZHNhR1JIVlhkSWFHTk9UV3BOZDAxcVJURk5WR3Q2VFhwTmVWZG9ZMDVOYWsxM1RXcEZNVTFVYXpCTmVrMTVWMnBCUVUxR2EzZEZkMWxJQ2t0dldrbDZhakJEUVZGWlNVdHZXa2w2YWpCRVFWRmpSRkZuUVVWV1YzSk9Na0Y1WXpOVk9EQlNRbTV4Y2taemMwTllja1pGVkdWNVRYTnJVV2hNUVZnS1lVOUJZbUZRZVd4TVlUWkhhWFZvY2xwVlJXUXJhVEpSSzJ0MmRHeFBTazQyVjNaS1lXOUphWEpIVlZWM09EUnpZMHRQUTBGdVRYZG5aMHAyVFVFMFJ3cEJNVlZrUkhkRlFpOTNVVVZCZDBsSVowUkJWRUpuVGxaSVUxVkZSRVJCUzBKblozSkNaMFZHUWxGalJFRjZRV1JDWjA1V1NGRTBSVVpuVVZWbldVNTVDa05hU0ZWd2EzcENabkZzWmxOb01pdGtWaTl1Y1djNGQwaDNXVVJXVWpCcVFrSm5kMFp2UVZVek9WQndlakZaYTBWYVlqVnhUbXB3UzBaWGFYaHBORmtLV2tRNGQySjNXVVJXVWpCU1FWRklMMEpIVlhkWk5GcG9ZVWhTTUdOSVRUWk1lVGx1WVZoU2IyUlhTWFZaTWpsMFRESjRhR1JZU214aWJsSjZZVmN4ZGdwaWFUbDNZMjA1TWxwWE5XaGliVTVzVEZjMWQySlRNVEJhV0U0d1RIazFibUZZVW05a1YwbDJaREk1ZVdFeVduTmlNMlI2VEROS2JHSkhWbWhqTWxWMUNtVlhNWE5SU0Vwc1dtNU5kbUZIVm1oYVNFMTJZbGRHY0dKcVFUVkNaMjl5UW1kRlJVRlpUeTlOUVVWQ1FrTjBiMlJJVW5kamVtOTJURE5TZG1FeVZuVUtURzFHYW1SSGJIWmliazExV2pKc01HRklWbWxrV0U1c1kyMU9kbUp1VW14aWJsRjFXVEk1ZEUxQ09FZERhWE5IUVZGUlFtYzNPSGRCVVVsRlJWaGtkZ3BqYlhSdFlrYzVNMWd5VW5Cak0wSm9aRWRPYjAxRVdVZERhWE5IUVZGUlFtYzNPSGRCVVUxRlMwUkZNbGx0Um1sYWJWcHBUMVJGTVUxNlozaE5WMVY0Q2s5VVRtcE5SRVUxVDFSTk5VMTZhM2hOZWxVelRYcGplVmxxU1RGWk1sVjNTbWRaUzB0M1dVSkNRVWRFZG5wQlFrSkJVVmxWU0ZacFlrZHNlbUZEUWxFS1dWZE9jbGxYWkd4SlNGSjJTVWMxZDJKWGNIcE5RelJIUTJselIwRlJVVUpuTnpoM1FWRlZSVWxIZUdoa1dFcHNZbTVTZW1GWE1YWmlhVGwzWTIwNU1ncGFWelZvWW0xT2JFeFhOWGRpVXpFd1dsaE9NRTFDTUVkRGFYTkhRVkZSUW1jM09IZEJVVmxGUkROS2JGcHVUWFpoUjFab1draE5kbUpYUm5CaWFrTkNDbWwzV1V0TGQxbENRa0ZJVjJWUlNVVkJaMUk1UWtoelFXVlJRak5CVGpBNVRVZHlSM2g0UlhsWmVHdGxTRXBzYms1M1MybFRiRFkwTTJwNWRDODBaVXNLWTI5QmRrdGxOazlCUVVGQ2FHeGhVbGhPVFVGQlFWRkVRVVZuZDFKblNXaEJUMXBaU0VNeVFYbENORTF0TlhWV05tVjBhV1ZuWTJSdlFqVjBMek5STmdwbE9IQmhhREpDU0RZd2RYSkJhVVZCZGpseWRqWlhUa2w1VUdaWWNsQXhlWHA1YTFGc1pIYzVhVVY0VTBKb0wySnlUazVxVkV4NlVDdDNXWGREWjFsSkNrdHZXa2w2YWpCRlFYZE5SRnAzUVhkYVFVbDNWQ3R1VDFWalIyMVVLMHN4WjNSVkwwVlVhVXBsZDFKVVdIUllOV0pxUm1nd1FVVkVWM3BXUm14TVVVc0theXREVFVOeUswTnRhRXBuWm05aVpEZ3pjWGRCYWtGNk9WZHdOQzlyY2tsbmVTdHhSRGR2WlVOM2JGVklOelJOVG1kWGNIa3lVVlUxVDNnelNqWXhkd3BRTWk4d1R6ZGlhRWcxWmtSaFIzUlpWVVpMV25wM1FUMEtMUzB0TFMxRlRrUWdRMFZTVkVsR1NVTkJWRVV0TFMwdExRbz0iLCJzaWciOiJUVVZWUTBsUlJFcGhhRlJ3VTI1c2RqWkllbFZxTW5reEwxQkNXVXhHZVRob2FFb3JOV1ZCUWxrM2RYazRVbEJ6UjFGSlowcFdkVXd6UjNJNWVXSXlWRkJWUlUxek5rbGxhVFZJVUVoaWVVZHNObWw0WjJRME1YbDJlVEEzVWxFOSJ9XX0sImhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIyYzVhZjNiZThjNzcxYzAwYzVhZGYwNDAxMzQ5YTg1NjM5NjA3Nzg4MzQwNjRhMmYyOTk5YzY4YmZiMWI0Njg4In0sInBheWxvYWRIYXNoIjp7ImFsZ29yaXRobSI6InNoYTI1NiIsInZhbHVlIjoiNjg5ZTE2NmNlM2I1Zjk5MTgxZDExYjcyYjg2OTJkODEwYjJlM2NkMTdmZWNiZjBiNzRmNDBmYTRmNmUzNjNkNSJ9fX19" + } + ], + "timestampVerificationData": null + }, + "dsseEnvelope": { + "payload": "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogWwogICAgewogICAgICAibmFtZSI6ICJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhNTEyIjogIjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIgogICAgICB9CiAgICB9CiAgXSwKICAicHJlZGljYXRlVHlwZSI6ICJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuYy92MC4yIiwKICAicHJlZGljYXRlIjogewogICAgImJ1aWxkVHlwZSI6ICJodHRwczovL2dpdGh1Yi5jb20vbnBtL2NsaS9naGFAdjEiLAogICAgImJ1aWxkZXIiOiB7CiAgICAgICJpZCI6ICJodHRwczovL2dpdGh1Yi5jb20vbnBtL2NsaUA5LjUuMCIKICAgIH0sCiAgICAiaW52b2NhdGlvbiI6IHsKICAgICAgImNvbmZpZ1NvdXJjZSI6IHsKICAgICAgICAidXJpIjogImdpdCtodHRwczovL2dpdGh1Yi5jb20vbGF1cmVudHNpbW9uL3Byb3ZlbmFuY2UtbnBtLXRlc3RAcmVmcy9oZWFkcy9tYWluIiwKICAgICAgICAiZGlnZXN0IjogewogICAgICAgICAgInNoYTEiOiAiMTZiYWJmZmI5MTUzODExZTE5M2MwMTk5MzkzOTEzNTczNzJiMjVjZSIKICAgICAgICB9LAogICAgICAgICJlbnRyeVBvaW50IjogImxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbiIKICAgICAgfSwKICAgICAgInBhcmFtZXRlcnMiOiB7fSwKICAgICAgImVudmlyb25tZW50IjogewogICAgICAgICJHSVRIVUJfQUNUT1JfSUQiOiAiNjQ1MDUwOTkiLAogICAgICAgICJHSVRIVUJfRVZFTlRfTkFNRSI6ICJ3b3JrZmxvd19kaXNwYXRjaCIsCiAgICAgICAgIkdJVEhVQl9SRUYiOiAicmVmcy9oZWFkcy9tYWluIiwKICAgICAgICAiR0lUSFVCX1JFRl9UWVBFIjogImJyYW5jaCIsCiAgICAgICAgIkdJVEhVQl9SRVBPU0lUT1JZIjogImxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0IiwKICAgICAgICAiR0lUSFVCX1JFUE9TSVRPUllfSUQiOiAiNjAyMjIzOTQ1IiwKICAgICAgICAiR0lUSFVCX1JFUE9TSVRPUllfT1dORVJfSUQiOiAiNjQ1MDUwOTkiLAogICAgICAgICJHSVRIVUJfUlVOX0FUVEVNUFQiOiAiMSIsCiAgICAgICAgIkdJVEhVQl9SVU5fSUQiOiAiNDE4NzQ2NDU3NyIsCiAgICAgICAgIkdJVEhVQl9SVU5fTlVNQkVSIjogIjIiLAogICAgICAgICJHSVRIVUJfU0hBIjogIjE2YmFiZmZiOTE1MzgxMWUxOTNjMDE5OTM5MzkxMzU3MzcyYjI1Y2UiLAogICAgICAgICJHSVRIVUJfV09SS0ZMT1dfUkVGIjogImxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbiIsCiAgICAgICAgIkdJVEhVQl9XT1JLRkxPV19TSEEiOiAiMTZiYWJmZmI5MTUzODExZTE5M2MwMTk5MzkzOTEzNTczNzJiMjVjZSIKICAgICAgfQogICAgfSwKICAgICJtZXRhZGF0YSI6IHsKICAgICAgImJ1aWxkSW52b2NhdGlvbklkIjogIjQxODc0NjQ1NzctMSIsCiAgICAgICJjb21wbGV0ZW5lc3MiOiB7CiAgICAgICAgInBhcmFtZXRlcnMiOiBmYWxzZSwKICAgICAgICAiZW52aXJvbm1lbnQiOiBmYWxzZSwKICAgICAgICAibWF0ZXJpYWxzIjogZmFsc2UKICAgICAgfSwKICAgICAgInJlcHJvZHVjaWJsZSI6IGZhbHNlCiAgICB9LAogICAgIm1hdGVyaWFscyI6IFsKICAgICAgewogICAgICAgICJ1cmkiOiAiZ2l0K2h0dHBzOi8vZ2l0aHViLmNvbS9sYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsCiAgICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAgICJzaGExIjogIjE2YmFiZmZiOTE1MzgxMWUxOTNjMDE5OTM5MzkxMzU3MzcyYjI1Y2UiCiAgICAgICAgfQogICAgICB9CiAgICBdCiAgfQp9Cg==", + "payloadType": "application/vnd.in-toto+json", + "signatures": [ + { + "sig": "MEUCIQDJahTpSnlv6HzUj2y1/PBYLFy8hhJ+5eABY7uy8RPsGQIgJVuL3Gr9yb2TPUEMs6Iei5HPHbyGl6ixgd41yvy07RQ=", + "keyid": "" + } + ] + } + } + }, + { + "predicateType": "https://github.com/npm/attestation/tree/main/specs/publish/v0.1", + "bundle": { + "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.1", + "verificationMaterial": { + "publicKey": { + "hint": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA" + }, + "tlogEntries": [ + { + "logIndex": "13420289", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "intoto", + "version": "0.0.2" + }, + "integratedTime": "1676489615", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCICYgQbiFj7t0A9B/p4Hkq5H0gB41InPBFFnhEeuP4Fo0AiEA7fGqVACs5cFpoQGHX8HVDq/jKBWbS0gutPXpcOz6r6g=" + }, + "inclusionProof": null, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7ImtleWlkIjoiU0hBMjU2OmpsM2J3c3d1ODBQampva0NnaDBvMnc1YzJVNExoUUFFNTdnajljejFrekEiLCJwdWJsaWNLZXkiOiJMUzB0TFMxQ1JVZEpUaUJRVlVKTVNVTWdTMFZaTFMwdExTMEtUVVpyZDBWM1dVaExiMXBKZW1vd1EwRlJXVWxMYjFwSmVtb3dSRUZSWTBSUlowRkZNVTlzWWpONlRVRkdSbmhZUzBocFNXdFJUelZqU2pOWmFHdzFhVFpWVUhBclNXaDFkR1ZDU21KMVNHTkJOVlZ2WjB0dk1FVlhkR3hYZDFjMlMxTmhTMjlVVGtWWlREZEtiRU5SYVZadWEyaENhM1JWWjJjOVBRb3RMUzB0TFVWT1JDQlFWVUpNU1VNZ1MwVlpMUzB0TFMwPSIsInNpZyI6IlRVVlJRMGxETURGaFJqbFFZVWxtSzNOcVkzRlBiVzQwUVZaVU56bFBWMFJuVkZGVk5XVXZiVkp0TVcweVNIWjVRV2xCY0hCNk1FWkxWVzFEVjJwdVUyUnJORzB5VkdGTlpXMXFSRXRqUlcxTVdFSTRWVVpFTlZsYWRETTJaejA5In1dfSwiaGFzaCI6eyJhbGdvcml0aG0iOiJzaGEyNTYiLCJ2YWx1ZSI6IjkxNDU3YjdiYzg1NTgwY2Y2NTAxNDM5NDU5ZDYyOWI0YzBlOTUxNmFjNzc3NTllNGQwNzMwZjVlMTUxNjRkMDcifSwicGF5bG9hZEhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI1ZmFmZTQwMmJiYzBiMTNhMmFmMmIzMjhjYmNjNmFiZTlmZTA1MGRkNDUzNjNkNTE1YWIyYzk4MjA3NDMwNjVkIn19fX0=" + } + ], + "timestampVerificationData": null + }, + "dsseEnvelope": { + "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInN1YmplY3QiOlt7Im5hbWUiOiJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwiZGlnZXN0Ijp7InNoYTUxMiI6IjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIn19XSwicHJlZGljYXRlVHlwZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsInByZWRpY2F0ZSI6eyJuYW1lIjoiQGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0IiwidmVyc2lvbiI6IjEuMC4wIiwicmVnaXN0cnkiOiJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyJ9fQ==", + "payloadType": "application/vnd.in-toto+json", + "signatures": [ + { + "sig": "MEQCIC01aF9PaIf+sjcqOmn4AVT79OWDgTQU5e/mRm1m2HvyAiAppz0FKUmCWjnSdk4m2TaMemjDKcEmLXB8UFD5YZt36g==", + "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA" + } + ] + } + } + } +] diff --git a/verifiers/internal/gha/testdata/npm-stmt-mismatch-prov-type.intoto.sigstore b/verifiers/internal/gha/testdata/npm-stmt-mismatch-prov-type.intoto.sigstore new file mode 100644 index 0000000..f20be81 --- /dev/null +++ b/verifiers/internal/gha/testdata/npm-stmt-mismatch-prov-type.intoto.sigstore @@ -0,0 +1,92 @@ +[ + { + "predicateType": "https://slsa.dev/provenance/v0.2", + "bundle": { + "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.1", + "verificationMaterial": { + "x509CertificateChain": { + "certificates": [ + { + "rawBytes": "MIIDzTCCA1SgAwIBAgIUSUNeEjOTOlxw2mAmVuog6waz+NcwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjMwMjE1MTkzMzMyWhcNMjMwMjE1MTk0MzMyWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVWrN2Ayc3U80RBnqrFssCXrFETeyMskQhLAXaOAbaPylLa6GiuhrZUEd+i2Q+kvtlOJN6WvJaoIirGUUw84scKOCAnMwggJvMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUgYNyCZHUpkzBfqlfSh2+dV/nqg8wHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wbwYDVR0RAQH/BGUwY4ZhaHR0cHM6Ly9naXRodWIuY29tL2xhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbjA5BgorBgEEAYO/MAEBBCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMB8GCisGAQQBg78wAQIEEXdvcmtmbG93X2Rpc3BhdGNoMDYGCisGAQQBg78wAQMEKDE2YmFiZmZiOTE1MzgxMWUxOTNjMDE5OTM5MzkxMzU3MzcyYjI1Y2UwJgYKKwYBBAGDvzABBAQYUHVibGlzaCBQYWNrYWdlIHRvIG5wbWpzMC4GCisGAQQBg78wAQUEIGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0MB0GCisGAQQBg78wAQYED3JlZnMvaGVhZHMvbWFpbjCBiwYKKwYBBAHWeQIEAgR9BHsAeQB3AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABhlaRXNMAAAQDAEgwRgIhAOZYHC2AyB4Mm5uV6etiegcdoB5t/3Q6e8pah2BH60urAiEAv9rv6WNIyPfXrP1yzykQldw9iExSBh/brNNjTLzP+wYwCgYIKoZIzj0EAwMDZwAwZAIwT+nOUcGmT+K1gtU/ETiJewRTXtX5bjFh0AEDWzVFlLQKk+CMCr+CmhJgfobd83qwAjAz9Wp4/krIgy+qD7oeCwlUH74MNgWpy2QU5Ox3J61wP2/0O7bhH5fDaGtYUFKZzwA=" + }, + { + "rawBytes": "MIICGjCCAaGgAwIBAgIUALnViVfnU0brJasmRkHrn/UnfaQwCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMjA0MTMyMDA2MTVaFw0zMTEwMDUxMzU2NThaMDcxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEeMBwGA1UEAxMVc2lnc3RvcmUtaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8RVS/ysH+NOvuDZyPIZtilgUF9NlarYpAd9HP1vBBH1U5CV77LSS7s0ZiH4nE7Hv7ptS6LvvR/STk798LVgMzLlJ4HeIfF3tHSaexLcYpSASr1kS0N/RgBJz/9jWCiXno3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU39Ppz1YkEZb5qNjpKFWixi4YZD8wHwYDVR0jBBgwFoAUWMAeX5FFpWapesyQoZMi0CrFxfowCgYIKoZIzj0EAwMDZwAwZAIwPCsQK4DYiZYDPIaDi5HFKnfxXx6ASSVmERfsynYBiX2X6SJRnZU84/9DZdnFvvxmAjBOt6QpBlc4J/0DxvkTCqpclvziL6BCCPnjdlIB3Pu3BxsPmygUY7Ii2zbdCdliiow=" + }, + { + "rawBytes": "MIIB9zCCAXygAwIBAgIUALZNAPFdxHPwjeDloDwyYChAO/4wCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMTEwMDcxMzU2NTlaFw0zMTEwMDUxMzU2NThaMCoxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjERMA8GA1UEAxMIc2lnc3RvcmUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT7XeFT4rb3PQGwS4IajtLk3/OlnpgangaBclYpsYBr5i+4ynB07ceb3LP0OIOZdxexX69c5iVuyJRQ+Hz05yi+UF3uBWAlHpiS5sh0+H2GHE7SXrk1EC5m1Tr19L9gg92jYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRYwB5fkUWlZql6zJChkyLQKsXF+jAfBgNVHSMEGDAWgBRYwB5fkUWlZql6zJChkyLQKsXF+jAKBggqhkjOPQQDAwNpADBmAjEAj1nHeXZp+13NWBNa+EDsDP8G1WWg1tCMWP/WHPqpaVo0jhsweNFZgSs0eE7wYI4qAjEA2WB9ot98sIkoF3vZYdd3/VtWB5b9TNMea7Ix/stJ5TfcLLeABLE4BNJOsQ4vnBHJ" + } + ] + }, + "tlogEntries": [ + { + "logIndex": "13420286", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "intoto", + "version": "0.0.2" + }, + "integratedTime": "1676489612", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCIG/LjJ5tqTgKvbA0F+96CJHIk2X0S+9cBz1Z04BfU7dLAiEA7cpf1Agv0VyEu0wR41nEZ9AZ6GVaYR5rf4AAYIZr4hk=" + }, + "inclusionProof": null, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7InB1YmxpY0tleSI6IkxTMHRMUzFDUlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVI2VkVORFFURlRaMEYzU1VKQlowbFZVMVZPWlVWcVQxUlBiSGgzTW0xQmJWWjFiMmMyZDJGNkswNWpkME5uV1VsTGIxcEplbW93UlVGM1RYY0tUbnBGVmsxQ1RVZEJNVlZGUTJoTlRXTXliRzVqTTFKMlkyMVZkVnBIVmpKTlVqUjNTRUZaUkZaUlVVUkZlRlo2WVZka2VtUkhPWGxhVXpGd1ltNVNiQXBqYlRGc1drZHNhR1JIVlhkSWFHTk9UV3BOZDAxcVJURk5WR3Q2VFhwTmVWZG9ZMDVOYWsxM1RXcEZNVTFVYXpCTmVrMTVWMnBCUVUxR2EzZEZkMWxJQ2t0dldrbDZhakJEUVZGWlNVdHZXa2w2YWpCRVFWRmpSRkZuUVVWV1YzSk9Na0Y1WXpOVk9EQlNRbTV4Y2taemMwTllja1pGVkdWNVRYTnJVV2hNUVZnS1lVOUJZbUZRZVd4TVlUWkhhWFZvY2xwVlJXUXJhVEpSSzJ0MmRHeFBTazQyVjNaS1lXOUphWEpIVlZWM09EUnpZMHRQUTBGdVRYZG5aMHAyVFVFMFJ3cEJNVlZrUkhkRlFpOTNVVVZCZDBsSVowUkJWRUpuVGxaSVUxVkZSRVJCUzBKblozSkNaMFZHUWxGalJFRjZRV1JDWjA1V1NGRTBSVVpuVVZWbldVNTVDa05hU0ZWd2EzcENabkZzWmxOb01pdGtWaTl1Y1djNGQwaDNXVVJXVWpCcVFrSm5kMFp2UVZVek9WQndlakZaYTBWYVlqVnhUbXB3UzBaWGFYaHBORmtLV2tRNGQySjNXVVJXVWpCU1FWRklMMEpIVlhkWk5GcG9ZVWhTTUdOSVRUWk1lVGx1WVZoU2IyUlhTWFZaTWpsMFRESjRhR1JZU214aWJsSjZZVmN4ZGdwaWFUbDNZMjA1TWxwWE5XaGliVTVzVEZjMWQySlRNVEJhV0U0d1RIazFibUZZVW05a1YwbDJaREk1ZVdFeVduTmlNMlI2VEROS2JHSkhWbWhqTWxWMUNtVlhNWE5SU0Vwc1dtNU5kbUZIVm1oYVNFMTJZbGRHY0dKcVFUVkNaMjl5UW1kRlJVRlpUeTlOUVVWQ1FrTjBiMlJJVW5kamVtOTJURE5TZG1FeVZuVUtURzFHYW1SSGJIWmliazExV2pKc01HRklWbWxrV0U1c1kyMU9kbUp1VW14aWJsRjFXVEk1ZEUxQ09FZERhWE5IUVZGUlFtYzNPSGRCVVVsRlJWaGtkZ3BqYlhSdFlrYzVNMWd5VW5Cak0wSm9aRWRPYjAxRVdVZERhWE5IUVZGUlFtYzNPSGRCVVUxRlMwUkZNbGx0Um1sYWJWcHBUMVJGTVUxNlozaE5WMVY0Q2s5VVRtcE5SRVUxVDFSTk5VMTZhM2hOZWxVelRYcGplVmxxU1RGWk1sVjNTbWRaUzB0M1dVSkNRVWRFZG5wQlFrSkJVVmxWU0ZacFlrZHNlbUZEUWxFS1dWZE9jbGxYWkd4SlNGSjJTVWMxZDJKWGNIcE5RelJIUTJselIwRlJVVUpuTnpoM1FWRlZSVWxIZUdoa1dFcHNZbTVTZW1GWE1YWmlhVGwzWTIwNU1ncGFWelZvWW0xT2JFeFhOWGRpVXpFd1dsaE9NRTFDTUVkRGFYTkhRVkZSUW1jM09IZEJVVmxGUkROS2JGcHVUWFpoUjFab1draE5kbUpYUm5CaWFrTkNDbWwzV1V0TGQxbENRa0ZJVjJWUlNVVkJaMUk1UWtoelFXVlJRak5CVGpBNVRVZHlSM2g0UlhsWmVHdGxTRXBzYms1M1MybFRiRFkwTTJwNWRDODBaVXNLWTI5QmRrdGxOazlCUVVGQ2FHeGhVbGhPVFVGQlFWRkVRVVZuZDFKblNXaEJUMXBaU0VNeVFYbENORTF0TlhWV05tVjBhV1ZuWTJSdlFqVjBMek5STmdwbE9IQmhhREpDU0RZd2RYSkJhVVZCZGpseWRqWlhUa2w1VUdaWWNsQXhlWHA1YTFGc1pIYzVhVVY0VTBKb0wySnlUazVxVkV4NlVDdDNXWGREWjFsSkNrdHZXa2w2YWpCRlFYZE5SRnAzUVhkYVFVbDNWQ3R1VDFWalIyMVVLMHN4WjNSVkwwVlVhVXBsZDFKVVdIUllOV0pxUm1nd1FVVkVWM3BXUm14TVVVc0theXREVFVOeUswTnRhRXBuWm05aVpEZ3pjWGRCYWtGNk9WZHdOQzlyY2tsbmVTdHhSRGR2WlVOM2JGVklOelJOVG1kWGNIa3lVVlUxVDNnelNqWXhkd3BRTWk4d1R6ZGlhRWcxWmtSaFIzUlpWVVpMV25wM1FUMEtMUzB0TFMxRlRrUWdRMFZTVkVsR1NVTkJWRVV0TFMwdExRbz0iLCJzaWciOiJUVVZWUTBsUlJFcGhhRlJ3VTI1c2RqWkllbFZxTW5reEwxQkNXVXhHZVRob2FFb3JOV1ZCUWxrM2RYazRVbEJ6UjFGSlowcFdkVXd6UjNJNWVXSXlWRkJWUlUxek5rbGxhVFZJVUVoaWVVZHNObWw0WjJRME1YbDJlVEEzVWxFOSJ9XX0sImhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIyYzVhZjNiZThjNzcxYzAwYzVhZGYwNDAxMzQ5YTg1NjM5NjA3Nzg4MzQwNjRhMmYyOTk5YzY4YmZiMWI0Njg4In0sInBheWxvYWRIYXNoIjp7ImFsZ29yaXRobSI6InNoYTI1NiIsInZhbHVlIjoiNjg5ZTE2NmNlM2I1Zjk5MTgxZDExYjcyYjg2OTJkODEwYjJlM2NkMTdmZWNiZjBiNzRmNDBmYTRmNmUzNjNkNSJ9fX19" + } + ], + "timestampVerificationData": null + }, + "dsseEnvelope": { + "payload": "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50QS92MC4xIiwKICAic3ViamVjdCI6IFsKICAgIHsKICAgICAgIm5hbWUiOiAicGtnOm5wbS8lNDBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdEAxLjAuMCIsCiAgICAgICJkaWdlc3QiOiB7CiAgICAgICAgInNoYTUxMiI6ICIyOWQxOWYyNjIzM2Y0NDQxMzI4NDEyYjM0ZmQ3M2VkMTA0ZWNmZWY2MmYxNDA5Nzg5MGNjY2Y3NDU1YjUyMWI2NWM1YWNmZjg1MTg0OWZhYTg1Yzg1Mzk1YWEyMmQ0MDE0MzZmMDFmM2FmYjYxYjE5Yzc4MGU5MDZjODhjN2YyMCIKICAgICAgfQogICAgfQogIF0sCiAgInByZWRpY2F0ZVR5cGUiOiAiaHR0cHM6Ly9zbHNhLmRldi9wcm92ZW5hbmNlL3YwLjIiLAogICJwcmVkaWNhdGUiOiB7CiAgICAiYnVpbGRUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vY2xpL2doYUB2MSIsCiAgICAiYnVpbGRlciI6IHsKICAgICAgImlkIjogImh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vY2xpQDkuNS4wIgogICAgfSwKICAgICJpbnZvY2F0aW9uIjogewogICAgICAiY29uZmlnU291cmNlIjogewogICAgICAgICJ1cmkiOiAiZ2l0K2h0dHBzOi8vZ2l0aHViLmNvbS9sYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdEByZWZzL2hlYWRzL21haW4iLAogICAgICAgICJkaWdlc3QiOiB7CiAgICAgICAgICAic2hhMSI6ICIxNmJhYmZmYjkxNTM4MTFlMTkzYzAxOTkzOTM5MTM1NzM3MmIyNWNlIgogICAgICAgIH0sCiAgICAgICAgImVudHJ5UG9pbnQiOiAibGF1cmVudHNpbW9uL3Byb3ZlbmFuY2UtbnBtLXRlc3QvLmdpdGh1Yi93b3JrZmxvd3MvcmVsZWFzZS55bWxAcmVmcy9oZWFkcy9tYWluIgogICAgICB9LAogICAgICAicGFyYW1ldGVycyI6IHt9LAogICAgICAiZW52aXJvbm1lbnQiOiB7CiAgICAgICAgIkdJVEhVQl9BQ1RPUl9JRCI6ICI2NDUwNTA5OSIsCiAgICAgICAgIkdJVEhVQl9FVkVOVF9OQU1FIjogIndvcmtmbG93X2Rpc3BhdGNoIiwKICAgICAgICAiR0lUSFVCX1JFRiI6ICJyZWZzL2hlYWRzL21haW4iLAogICAgICAgICJHSVRIVUJfUkVGX1RZUEUiOiAiYnJhbmNoIiwKICAgICAgICAiR0lUSFVCX1JFUE9TSVRPUlkiOiAibGF1cmVudHNpbW9uL3Byb3ZlbmFuY2UtbnBtLXRlc3QiLAogICAgICAgICJHSVRIVUJfUkVQT1NJVE9SWV9JRCI6ICI2MDIyMjM5NDUiLAogICAgICAgICJHSVRIVUJfUkVQT1NJVE9SWV9PV05FUl9JRCI6ICI2NDUwNTA5OSIsCiAgICAgICAgIkdJVEhVQl9SVU5fQVRURU1QVCI6ICIxIiwKICAgICAgICAiR0lUSFVCX1JVTl9JRCI6ICI0MTg3NDY0NTc3IiwKICAgICAgICAiR0lUSFVCX1JVTl9OVU1CRVIiOiAiMiIsCiAgICAgICAgIkdJVEhVQl9TSEEiOiAiMTZiYWJmZmI5MTUzODExZTE5M2MwMTk5MzkzOTEzNTczNzJiMjVjZSIsCiAgICAgICAgIkdJVEhVQl9XT1JLRkxPV19SRUYiOiAibGF1cmVudHNpbW9uL3Byb3ZlbmFuY2UtbnBtLXRlc3QvLmdpdGh1Yi93b3JrZmxvd3MvcmVsZWFzZS55bWxAcmVmcy9oZWFkcy9tYWluIiwKICAgICAgICAiR0lUSFVCX1dPUktGTE9XX1NIQSI6ICIxNmJhYmZmYjkxNTM4MTFlMTkzYzAxOTkzOTM5MTM1NzM3MmIyNWNlIgogICAgICB9CiAgICB9LAogICAgIm1ldGFkYXRhIjogewogICAgICAiYnVpbGRJbnZvY2F0aW9uSWQiOiAiNDE4NzQ2NDU3Ny0xIiwKICAgICAgImNvbXBsZXRlbmVzcyI6IHsKICAgICAgICAicGFyYW1ldGVycyI6IGZhbHNlLAogICAgICAgICJlbnZpcm9ubWVudCI6IGZhbHNlLAogICAgICAgICJtYXRlcmlhbHMiOiBmYWxzZQogICAgICB9LAogICAgICAicmVwcm9kdWNpYmxlIjogZmFsc2UKICAgIH0sCiAgICAibWF0ZXJpYWxzIjogWwogICAgICB7CiAgICAgICAgInVyaSI6ICJnaXQraHR0cHM6Ly9naXRodWIuY29tL2xhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0IiwKICAgICAgICAiZGlnZXN0IjogewogICAgICAgICAgInNoYTEiOiAiMTZiYWJmZmI5MTUzODExZTE5M2MwMTk5MzkzOTEzNTczNzJiMjVjZSIKICAgICAgICB9CiAgICAgIH0KICAgIF0KICB9Cn0K", + "payloadType": "application/vnd.in-toto+json", + "signatures": [ + { + "sig": "MEUCIQDJahTpSnlv6HzUj2y1/PBYLFy8hhJ+5eABY7uy8RPsGQIgJVuL3Gr9yb2TPUEMs6Iei5HPHbyGl6ixgd41yvy07RQ=", + "keyid": "" + } + ] + } + } + }, + { + "predicateType": "https://github.com/npm/attestation/tree/main/specs/publish/v0.1", + "bundle": { + "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.1", + "verificationMaterial": { + "publicKey": { + "hint": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA" + }, + "tlogEntries": [ + { + "logIndex": "13420289", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "intoto", + "version": "0.0.2" + }, + "integratedTime": "1676489615", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCICYgQbiFj7t0A9B/p4Hkq5H0gB41InPBFFnhEeuP4Fo0AiEA7fGqVACs5cFpoQGHX8HVDq/jKBWbS0gutPXpcOz6r6g=" + }, + "inclusionProof": null, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7ImtleWlkIjoiU0hBMjU2OmpsM2J3c3d1ODBQampva0NnaDBvMnc1YzJVNExoUUFFNTdnajljejFrekEiLCJwdWJsaWNLZXkiOiJMUzB0TFMxQ1JVZEpUaUJRVlVKTVNVTWdTMFZaTFMwdExTMEtUVVpyZDBWM1dVaExiMXBKZW1vd1EwRlJXVWxMYjFwSmVtb3dSRUZSWTBSUlowRkZNVTlzWWpONlRVRkdSbmhZUzBocFNXdFJUelZqU2pOWmFHdzFhVFpWVUhBclNXaDFkR1ZDU21KMVNHTkJOVlZ2WjB0dk1FVlhkR3hYZDFjMlMxTmhTMjlVVGtWWlREZEtiRU5SYVZadWEyaENhM1JWWjJjOVBRb3RMUzB0TFVWT1JDQlFWVUpNU1VNZ1MwVlpMUzB0TFMwPSIsInNpZyI6IlRVVlJRMGxETURGaFJqbFFZVWxtSzNOcVkzRlBiVzQwUVZaVU56bFBWMFJuVkZGVk5XVXZiVkp0TVcweVNIWjVRV2xCY0hCNk1FWkxWVzFEVjJwdVUyUnJORzB5VkdGTlpXMXFSRXRqUlcxTVdFSTRWVVpFTlZsYWRETTJaejA5In1dfSwiaGFzaCI6eyJhbGdvcml0aG0iOiJzaGEyNTYiLCJ2YWx1ZSI6IjkxNDU3YjdiYzg1NTgwY2Y2NTAxNDM5NDU5ZDYyOWI0YzBlOTUxNmFjNzc3NTllNGQwNzMwZjVlMTUxNjRkMDcifSwicGF5bG9hZEhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI1ZmFmZTQwMmJiYzBiMTNhMmFmMmIzMjhjYmNjNmFiZTlmZTA1MGRkNDUzNjNkNTE1YWIyYzk4MjA3NDMwNjVkIn19fX0=" + } + ], + "timestampVerificationData": null + }, + "dsseEnvelope": { + "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInN1YmplY3QiOlt7Im5hbWUiOiJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwiZGlnZXN0Ijp7InNoYTUxMiI6IjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIn19XSwicHJlZGljYXRlVHlwZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vYXR0ZXN0YXRpb24vdHJlZS9tYWluL3NwZWNzL3B1Ymxpc2gvdjAuMSIsInByZWRpY2F0ZSI6eyJuYW1lIjoiQGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0IiwidmVyc2lvbiI6IjEuMC4wIiwicmVnaXN0cnkiOiJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyJ9fQ==", + "payloadType": "application/vnd.in-toto+json", + "signatures": [ + { + "sig": "MEQCIC01aF9PaIf+sjcqOmn4AVT79OWDgTQU5e/mRm1m2HvyAiAppz0FKUmCWjnSdk4m2TaMemjDKcEmLXB8UFD5YZt36g==", + "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA" + } + ] + } + } + } +] diff --git a/verifiers/internal/gha/testdata/npm-stmt-mismatch-pub-predicatetype.intoto.sigstore b/verifiers/internal/gha/testdata/npm-stmt-mismatch-pub-predicatetype.intoto.sigstore new file mode 100644 index 0000000..3a6ac5f --- /dev/null +++ b/verifiers/internal/gha/testdata/npm-stmt-mismatch-pub-predicatetype.intoto.sigstore @@ -0,0 +1,92 @@ +[ + { + "predicateType": "https://slsa.dev/provenance/v0.2", + "bundle": { + "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.1", + "verificationMaterial": { + "x509CertificateChain": { + "certificates": [ + { + "rawBytes": "MIIDzTCCA1SgAwIBAgIUSUNeEjOTOlxw2mAmVuog6waz+NcwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjMwMjE1MTkzMzMyWhcNMjMwMjE1MTk0MzMyWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVWrN2Ayc3U80RBnqrFssCXrFETeyMskQhLAXaOAbaPylLa6GiuhrZUEd+i2Q+kvtlOJN6WvJaoIirGUUw84scKOCAnMwggJvMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUgYNyCZHUpkzBfqlfSh2+dV/nqg8wHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wbwYDVR0RAQH/BGUwY4ZhaHR0cHM6Ly9naXRodWIuY29tL2xhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbjA5BgorBgEEAYO/MAEBBCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMB8GCisGAQQBg78wAQIEEXdvcmtmbG93X2Rpc3BhdGNoMDYGCisGAQQBg78wAQMEKDE2YmFiZmZiOTE1MzgxMWUxOTNjMDE5OTM5MzkxMzU3MzcyYjI1Y2UwJgYKKwYBBAGDvzABBAQYUHVibGlzaCBQYWNrYWdlIHRvIG5wbWpzMC4GCisGAQQBg78wAQUEIGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0MB0GCisGAQQBg78wAQYED3JlZnMvaGVhZHMvbWFpbjCBiwYKKwYBBAHWeQIEAgR9BHsAeQB3AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABhlaRXNMAAAQDAEgwRgIhAOZYHC2AyB4Mm5uV6etiegcdoB5t/3Q6e8pah2BH60urAiEAv9rv6WNIyPfXrP1yzykQldw9iExSBh/brNNjTLzP+wYwCgYIKoZIzj0EAwMDZwAwZAIwT+nOUcGmT+K1gtU/ETiJewRTXtX5bjFh0AEDWzVFlLQKk+CMCr+CmhJgfobd83qwAjAz9Wp4/krIgy+qD7oeCwlUH74MNgWpy2QU5Ox3J61wP2/0O7bhH5fDaGtYUFKZzwA=" + }, + { + "rawBytes": "MIICGjCCAaGgAwIBAgIUALnViVfnU0brJasmRkHrn/UnfaQwCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMjA0MTMyMDA2MTVaFw0zMTEwMDUxMzU2NThaMDcxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEeMBwGA1UEAxMVc2lnc3RvcmUtaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8RVS/ysH+NOvuDZyPIZtilgUF9NlarYpAd9HP1vBBH1U5CV77LSS7s0ZiH4nE7Hv7ptS6LvvR/STk798LVgMzLlJ4HeIfF3tHSaexLcYpSASr1kS0N/RgBJz/9jWCiXno3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU39Ppz1YkEZb5qNjpKFWixi4YZD8wHwYDVR0jBBgwFoAUWMAeX5FFpWapesyQoZMi0CrFxfowCgYIKoZIzj0EAwMDZwAwZAIwPCsQK4DYiZYDPIaDi5HFKnfxXx6ASSVmERfsynYBiX2X6SJRnZU84/9DZdnFvvxmAjBOt6QpBlc4J/0DxvkTCqpclvziL6BCCPnjdlIB3Pu3BxsPmygUY7Ii2zbdCdliiow=" + }, + { + "rawBytes": "MIIB9zCCAXygAwIBAgIUALZNAPFdxHPwjeDloDwyYChAO/4wCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMTEwMDcxMzU2NTlaFw0zMTEwMDUxMzU2NThaMCoxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjERMA8GA1UEAxMIc2lnc3RvcmUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT7XeFT4rb3PQGwS4IajtLk3/OlnpgangaBclYpsYBr5i+4ynB07ceb3LP0OIOZdxexX69c5iVuyJRQ+Hz05yi+UF3uBWAlHpiS5sh0+H2GHE7SXrk1EC5m1Tr19L9gg92jYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRYwB5fkUWlZql6zJChkyLQKsXF+jAfBgNVHSMEGDAWgBRYwB5fkUWlZql6zJChkyLQKsXF+jAKBggqhkjOPQQDAwNpADBmAjEAj1nHeXZp+13NWBNa+EDsDP8G1WWg1tCMWP/WHPqpaVo0jhsweNFZgSs0eE7wYI4qAjEA2WB9ot98sIkoF3vZYdd3/VtWB5b9TNMea7Ix/stJ5TfcLLeABLE4BNJOsQ4vnBHJ" + } + ] + }, + "tlogEntries": [ + { + "logIndex": "13420286", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "intoto", + "version": "0.0.2" + }, + "integratedTime": "1676489612", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCIG/LjJ5tqTgKvbA0F+96CJHIk2X0S+9cBz1Z04BfU7dLAiEA7cpf1Agv0VyEu0wR41nEZ9AZ6GVaYR5rf4AAYIZr4hk=" + }, + "inclusionProof": null, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7InB1YmxpY0tleSI6IkxTMHRMUzFDUlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVI2VkVORFFURlRaMEYzU1VKQlowbFZVMVZPWlVWcVQxUlBiSGgzTW0xQmJWWjFiMmMyZDJGNkswNWpkME5uV1VsTGIxcEplbW93UlVGM1RYY0tUbnBGVmsxQ1RVZEJNVlZGUTJoTlRXTXliRzVqTTFKMlkyMVZkVnBIVmpKTlVqUjNTRUZaUkZaUlVVUkZlRlo2WVZka2VtUkhPWGxhVXpGd1ltNVNiQXBqYlRGc1drZHNhR1JIVlhkSWFHTk9UV3BOZDAxcVJURk5WR3Q2VFhwTmVWZG9ZMDVOYWsxM1RXcEZNVTFVYXpCTmVrMTVWMnBCUVUxR2EzZEZkMWxJQ2t0dldrbDZhakJEUVZGWlNVdHZXa2w2YWpCRVFWRmpSRkZuUVVWV1YzSk9Na0Y1WXpOVk9EQlNRbTV4Y2taemMwTllja1pGVkdWNVRYTnJVV2hNUVZnS1lVOUJZbUZRZVd4TVlUWkhhWFZvY2xwVlJXUXJhVEpSSzJ0MmRHeFBTazQyVjNaS1lXOUphWEpIVlZWM09EUnpZMHRQUTBGdVRYZG5aMHAyVFVFMFJ3cEJNVlZrUkhkRlFpOTNVVVZCZDBsSVowUkJWRUpuVGxaSVUxVkZSRVJCUzBKblozSkNaMFZHUWxGalJFRjZRV1JDWjA1V1NGRTBSVVpuVVZWbldVNTVDa05hU0ZWd2EzcENabkZzWmxOb01pdGtWaTl1Y1djNGQwaDNXVVJXVWpCcVFrSm5kMFp2UVZVek9WQndlakZaYTBWYVlqVnhUbXB3UzBaWGFYaHBORmtLV2tRNGQySjNXVVJXVWpCU1FWRklMMEpIVlhkWk5GcG9ZVWhTTUdOSVRUWk1lVGx1WVZoU2IyUlhTWFZaTWpsMFRESjRhR1JZU214aWJsSjZZVmN4ZGdwaWFUbDNZMjA1TWxwWE5XaGliVTVzVEZjMWQySlRNVEJhV0U0d1RIazFibUZZVW05a1YwbDJaREk1ZVdFeVduTmlNMlI2VEROS2JHSkhWbWhqTWxWMUNtVlhNWE5SU0Vwc1dtNU5kbUZIVm1oYVNFMTJZbGRHY0dKcVFUVkNaMjl5UW1kRlJVRlpUeTlOUVVWQ1FrTjBiMlJJVW5kamVtOTJURE5TZG1FeVZuVUtURzFHYW1SSGJIWmliazExV2pKc01HRklWbWxrV0U1c1kyMU9kbUp1VW14aWJsRjFXVEk1ZEUxQ09FZERhWE5IUVZGUlFtYzNPSGRCVVVsRlJWaGtkZ3BqYlhSdFlrYzVNMWd5VW5Cak0wSm9aRWRPYjAxRVdVZERhWE5IUVZGUlFtYzNPSGRCVVUxRlMwUkZNbGx0Um1sYWJWcHBUMVJGTVUxNlozaE5WMVY0Q2s5VVRtcE5SRVUxVDFSTk5VMTZhM2hOZWxVelRYcGplVmxxU1RGWk1sVjNTbWRaUzB0M1dVSkNRVWRFZG5wQlFrSkJVVmxWU0ZacFlrZHNlbUZEUWxFS1dWZE9jbGxYWkd4SlNGSjJTVWMxZDJKWGNIcE5RelJIUTJselIwRlJVVUpuTnpoM1FWRlZSVWxIZUdoa1dFcHNZbTVTZW1GWE1YWmlhVGwzWTIwNU1ncGFWelZvWW0xT2JFeFhOWGRpVXpFd1dsaE9NRTFDTUVkRGFYTkhRVkZSUW1jM09IZEJVVmxGUkROS2JGcHVUWFpoUjFab1draE5kbUpYUm5CaWFrTkNDbWwzV1V0TGQxbENRa0ZJVjJWUlNVVkJaMUk1UWtoelFXVlJRak5CVGpBNVRVZHlSM2g0UlhsWmVHdGxTRXBzYms1M1MybFRiRFkwTTJwNWRDODBaVXNLWTI5QmRrdGxOazlCUVVGQ2FHeGhVbGhPVFVGQlFWRkVRVVZuZDFKblNXaEJUMXBaU0VNeVFYbENORTF0TlhWV05tVjBhV1ZuWTJSdlFqVjBMek5STmdwbE9IQmhhREpDU0RZd2RYSkJhVVZCZGpseWRqWlhUa2w1VUdaWWNsQXhlWHA1YTFGc1pIYzVhVVY0VTBKb0wySnlUazVxVkV4NlVDdDNXWGREWjFsSkNrdHZXa2w2YWpCRlFYZE5SRnAzUVhkYVFVbDNWQ3R1VDFWalIyMVVLMHN4WjNSVkwwVlVhVXBsZDFKVVdIUllOV0pxUm1nd1FVVkVWM3BXUm14TVVVc0theXREVFVOeUswTnRhRXBuWm05aVpEZ3pjWGRCYWtGNk9WZHdOQzlyY2tsbmVTdHhSRGR2WlVOM2JGVklOelJOVG1kWGNIa3lVVlUxVDNnelNqWXhkd3BRTWk4d1R6ZGlhRWcxWmtSaFIzUlpWVVpMV25wM1FUMEtMUzB0TFMxRlRrUWdRMFZTVkVsR1NVTkJWRVV0TFMwdExRbz0iLCJzaWciOiJUVVZWUTBsUlJFcGhhRlJ3VTI1c2RqWkllbFZxTW5reEwxQkNXVXhHZVRob2FFb3JOV1ZCUWxrM2RYazRVbEJ6UjFGSlowcFdkVXd6UjNJNWVXSXlWRkJWUlUxek5rbGxhVFZJVUVoaWVVZHNObWw0WjJRME1YbDJlVEEzVWxFOSJ9XX0sImhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIyYzVhZjNiZThjNzcxYzAwYzVhZGYwNDAxMzQ5YTg1NjM5NjA3Nzg4MzQwNjRhMmYyOTk5YzY4YmZiMWI0Njg4In0sInBheWxvYWRIYXNoIjp7ImFsZ29yaXRobSI6InNoYTI1NiIsInZhbHVlIjoiNjg5ZTE2NmNlM2I1Zjk5MTgxZDExYjcyYjg2OTJkODEwYjJlM2NkMTdmZWNiZjBiNzRmNDBmYTRmNmUzNjNkNSJ9fX19" + } + ], + "timestampVerificationData": null + }, + "dsseEnvelope": { + "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInN1YmplY3QiOlt7Im5hbWUiOiJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwiZGlnZXN0Ijp7InNoYTUxMiI6IjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIn19XSwicHJlZGljYXRlVHlwZSI6Imh0dHBzOi8vc2xzYS5kZXYvcHJvdmVuYW5jZS92MC4yIiwicHJlZGljYXRlIjp7ImJ1aWxkVHlwZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vY2xpL2doYUB2MSIsImJ1aWxkZXIiOnsiaWQiOiJodHRwczovL2dpdGh1Yi5jb20vbnBtL2NsaUA5LjUuMCJ9LCJpbnZvY2F0aW9uIjp7ImNvbmZpZ1NvdXJjZSI6eyJ1cmkiOiJnaXQraHR0cHM6Ly9naXRodWIuY29tL2xhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QHJlZnMvaGVhZHMvbWFpbiIsImRpZ2VzdCI6eyJzaGExIjoiMTZiYWJmZmI5MTUzODExZTE5M2MwMTk5MzkzOTEzNTczNzJiMjVjZSJ9LCJlbnRyeVBvaW50IjoibGF1cmVudHNpbW9uL3Byb3ZlbmFuY2UtbnBtLXRlc3QvLmdpdGh1Yi93b3JrZmxvd3MvcmVsZWFzZS55bWxAcmVmcy9oZWFkcy9tYWluIn0sInBhcmFtZXRlcnMiOnt9LCJlbnZpcm9ubWVudCI6eyJHSVRIVUJfQUNUT1JfSUQiOiI2NDUwNTA5OSIsIkdJVEhVQl9FVkVOVF9OQU1FIjoid29ya2Zsb3dfZGlzcGF0Y2giLCJHSVRIVUJfUkVGIjoicmVmcy9oZWFkcy9tYWluIiwiR0lUSFVCX1JFRl9UWVBFIjoiYnJhbmNoIiwiR0lUSFVCX1JFUE9TSVRPUlkiOiJsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsIkdJVEhVQl9SRVBPU0lUT1JZX0lEIjoiNjAyMjIzOTQ1IiwiR0lUSFVCX1JFUE9TSVRPUllfT1dORVJfSUQiOiI2NDUwNTA5OSIsIkdJVEhVQl9SVU5fQVRURU1QVCI6IjEiLCJHSVRIVUJfUlVOX0lEIjoiNDE4NzQ2NDU3NyIsIkdJVEhVQl9SVU5fTlVNQkVSIjoiMiIsIkdJVEhVQl9TSEEiOiIxNmJhYmZmYjkxNTM4MTFlMTkzYzAxOTkzOTM5MTM1NzM3MmIyNWNlIiwiR0lUSFVCX1dPUktGTE9XX1JFRiI6ImxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbiIsIkdJVEhVQl9XT1JLRkxPV19TSEEiOiIxNmJhYmZmYjkxNTM4MTFlMTkzYzAxOTkzOTM5MTM1NzM3MmIyNWNlIn19LCJtZXRhZGF0YSI6eyJidWlsZEludm9jYXRpb25JZCI6IjQxODc0NjQ1NzctMSIsImNvbXBsZXRlbmVzcyI6eyJwYXJhbWV0ZXJzIjpmYWxzZSwiZW52aXJvbm1lbnQiOmZhbHNlLCJtYXRlcmlhbHMiOmZhbHNlfSwicmVwcm9kdWNpYmxlIjpmYWxzZX0sIm1hdGVyaWFscyI6W3sidXJpIjoiZ2l0K2h0dHBzOi8vZ2l0aHViLmNvbS9sYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsImRpZ2VzdCI6eyJzaGExIjoiMTZiYWJmZmI5MTUzODExZTE5M2MwMTk5MzkzOTEzNTczNzJiMjVjZSJ9fV19fQ==", + "payloadType": "application/vnd.in-toto+json", + "signatures": [ + { + "sig": "MEUCIQDJahTpSnlv6HzUj2y1/PBYLFy8hhJ+5eABY7uy8RPsGQIgJVuL3Gr9yb2TPUEMs6Iei5HPHbyGl6ixgd41yvy07RQ=", + "keyid": "" + } + ] + } + } + }, + { + "predicateType": "https://github.com/npm/attestation/tree/main/specs/publish/v0.1", + "bundle": { + "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.1", + "verificationMaterial": { + "publicKey": { + "hint": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA" + }, + "tlogEntries": [ + { + "logIndex": "13420289", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "intoto", + "version": "0.0.2" + }, + "integratedTime": "1676489615", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCICYgQbiFj7t0A9B/p4Hkq5H0gB41InPBFFnhEeuP4Fo0AiEA7fGqVACs5cFpoQGHX8HVDq/jKBWbS0gutPXpcOz6r6g=" + }, + "inclusionProof": null, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7ImtleWlkIjoiU0hBMjU2OmpsM2J3c3d1ODBQampva0NnaDBvMnc1YzJVNExoUUFFNTdnajljejFrekEiLCJwdWJsaWNLZXkiOiJMUzB0TFMxQ1JVZEpUaUJRVlVKTVNVTWdTMFZaTFMwdExTMEtUVVpyZDBWM1dVaExiMXBKZW1vd1EwRlJXVWxMYjFwSmVtb3dSRUZSWTBSUlowRkZNVTlzWWpONlRVRkdSbmhZUzBocFNXdFJUelZqU2pOWmFHdzFhVFpWVUhBclNXaDFkR1ZDU21KMVNHTkJOVlZ2WjB0dk1FVlhkR3hYZDFjMlMxTmhTMjlVVGtWWlREZEtiRU5SYVZadWEyaENhM1JWWjJjOVBRb3RMUzB0TFVWT1JDQlFWVUpNU1VNZ1MwVlpMUzB0TFMwPSIsInNpZyI6IlRVVlJRMGxETURGaFJqbFFZVWxtSzNOcVkzRlBiVzQwUVZaVU56bFBWMFJuVkZGVk5XVXZiVkp0TVcweVNIWjVRV2xCY0hCNk1FWkxWVzFEVjJwdVUyUnJORzB5VkdGTlpXMXFSRXRqUlcxTVdFSTRWVVpFTlZsYWRETTJaejA5In1dfSwiaGFzaCI6eyJhbGdvcml0aG0iOiJzaGEyNTYiLCJ2YWx1ZSI6IjkxNDU3YjdiYzg1NTgwY2Y2NTAxNDM5NDU5ZDYyOWI0YzBlOTUxNmFjNzc3NTllNGQwNzMwZjVlMTUxNjRkMDcifSwicGF5bG9hZEhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI1ZmFmZTQwMmJiYzBiMTNhMmFmMmIzMjhjYmNjNmFiZTlmZTA1MGRkNDUzNjNkNTE1YWIyYzk4MjA3NDMwNjVkIn19fX0=" + } + ], + "timestampVerificationData": null + }, + "dsseEnvelope": { + "payload": "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogWwogICAgewogICAgICAibmFtZSI6ICJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhNTEyIjogIjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIgogICAgICB9CiAgICB9CiAgXSwKICAicHJlZGljYXRlVHlwZSI6ICJodHRwczovL2dpdGh1Yi5jb20vbnBtL2F0dGVzdGF0aW9uL3RyZWUvbWFpbi9zcGVjcy9wdWJsaXMvdjAuMSIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJuYW1lIjogIkBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsCiAgICAidmVyc2lvbiI6ICIxLjAuMCIsCiAgICAicmVnaXN0cnkiOiAiaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmciCiAgfQp9Cg==", + "payloadType": "application/vnd.in-toto+json", + "signatures": [ + { + "sig": "MEQCIC01aF9PaIf+sjcqOmn4AVT79OWDgTQU5e/mRm1m2HvyAiAppz0FKUmCWjnSdk4m2TaMemjDKcEmLXB8UFD5YZt36g==", + "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA" + } + ] + } + } + } +] diff --git a/verifiers/internal/gha/testdata/npm-stmt-mismatch-pub-type.intoto.sigstore b/verifiers/internal/gha/testdata/npm-stmt-mismatch-pub-type.intoto.sigstore new file mode 100644 index 0000000..821037e --- /dev/null +++ b/verifiers/internal/gha/testdata/npm-stmt-mismatch-pub-type.intoto.sigstore @@ -0,0 +1,92 @@ +[ + { + "predicateType": "https://slsa.dev/provenance/v0.2", + "bundle": { + "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.1", + "verificationMaterial": { + "x509CertificateChain": { + "certificates": [ + { + "rawBytes": "MIIDzTCCA1SgAwIBAgIUSUNeEjOTOlxw2mAmVuog6waz+NcwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjMwMjE1MTkzMzMyWhcNMjMwMjE1MTk0MzMyWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVWrN2Ayc3U80RBnqrFssCXrFETeyMskQhLAXaOAbaPylLa6GiuhrZUEd+i2Q+kvtlOJN6WvJaoIirGUUw84scKOCAnMwggJvMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUgYNyCZHUpkzBfqlfSh2+dV/nqg8wHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wbwYDVR0RAQH/BGUwY4ZhaHR0cHM6Ly9naXRodWIuY29tL2xhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbjA5BgorBgEEAYO/MAEBBCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMB8GCisGAQQBg78wAQIEEXdvcmtmbG93X2Rpc3BhdGNoMDYGCisGAQQBg78wAQMEKDE2YmFiZmZiOTE1MzgxMWUxOTNjMDE5OTM5MzkxMzU3MzcyYjI1Y2UwJgYKKwYBBAGDvzABBAQYUHVibGlzaCBQYWNrYWdlIHRvIG5wbWpzMC4GCisGAQQBg78wAQUEIGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0MB0GCisGAQQBg78wAQYED3JlZnMvaGVhZHMvbWFpbjCBiwYKKwYBBAHWeQIEAgR9BHsAeQB3AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABhlaRXNMAAAQDAEgwRgIhAOZYHC2AyB4Mm5uV6etiegcdoB5t/3Q6e8pah2BH60urAiEAv9rv6WNIyPfXrP1yzykQldw9iExSBh/brNNjTLzP+wYwCgYIKoZIzj0EAwMDZwAwZAIwT+nOUcGmT+K1gtU/ETiJewRTXtX5bjFh0AEDWzVFlLQKk+CMCr+CmhJgfobd83qwAjAz9Wp4/krIgy+qD7oeCwlUH74MNgWpy2QU5Ox3J61wP2/0O7bhH5fDaGtYUFKZzwA=" + }, + { + "rawBytes": "MIICGjCCAaGgAwIBAgIUALnViVfnU0brJasmRkHrn/UnfaQwCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMjA0MTMyMDA2MTVaFw0zMTEwMDUxMzU2NThaMDcxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEeMBwGA1UEAxMVc2lnc3RvcmUtaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8RVS/ysH+NOvuDZyPIZtilgUF9NlarYpAd9HP1vBBH1U5CV77LSS7s0ZiH4nE7Hv7ptS6LvvR/STk798LVgMzLlJ4HeIfF3tHSaexLcYpSASr1kS0N/RgBJz/9jWCiXno3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU39Ppz1YkEZb5qNjpKFWixi4YZD8wHwYDVR0jBBgwFoAUWMAeX5FFpWapesyQoZMi0CrFxfowCgYIKoZIzj0EAwMDZwAwZAIwPCsQK4DYiZYDPIaDi5HFKnfxXx6ASSVmERfsynYBiX2X6SJRnZU84/9DZdnFvvxmAjBOt6QpBlc4J/0DxvkTCqpclvziL6BCCPnjdlIB3Pu3BxsPmygUY7Ii2zbdCdliiow=" + }, + { + "rawBytes": "MIIB9zCCAXygAwIBAgIUALZNAPFdxHPwjeDloDwyYChAO/4wCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMTEwMDcxMzU2NTlaFw0zMTEwMDUxMzU2NThaMCoxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjERMA8GA1UEAxMIc2lnc3RvcmUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT7XeFT4rb3PQGwS4IajtLk3/OlnpgangaBclYpsYBr5i+4ynB07ceb3LP0OIOZdxexX69c5iVuyJRQ+Hz05yi+UF3uBWAlHpiS5sh0+H2GHE7SXrk1EC5m1Tr19L9gg92jYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRYwB5fkUWlZql6zJChkyLQKsXF+jAfBgNVHSMEGDAWgBRYwB5fkUWlZql6zJChkyLQKsXF+jAKBggqhkjOPQQDAwNpADBmAjEAj1nHeXZp+13NWBNa+EDsDP8G1WWg1tCMWP/WHPqpaVo0jhsweNFZgSs0eE7wYI4qAjEA2WB9ot98sIkoF3vZYdd3/VtWB5b9TNMea7Ix/stJ5TfcLLeABLE4BNJOsQ4vnBHJ" + } + ] + }, + "tlogEntries": [ + { + "logIndex": "13420286", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "intoto", + "version": "0.0.2" + }, + "integratedTime": "1676489612", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCIG/LjJ5tqTgKvbA0F+96CJHIk2X0S+9cBz1Z04BfU7dLAiEA7cpf1Agv0VyEu0wR41nEZ9AZ6GVaYR5rf4AAYIZr4hk=" + }, + "inclusionProof": null, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7InB1YmxpY0tleSI6IkxTMHRMUzFDUlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVI2VkVORFFURlRaMEYzU1VKQlowbFZVMVZPWlVWcVQxUlBiSGgzTW0xQmJWWjFiMmMyZDJGNkswNWpkME5uV1VsTGIxcEplbW93UlVGM1RYY0tUbnBGVmsxQ1RVZEJNVlZGUTJoTlRXTXliRzVqTTFKMlkyMVZkVnBIVmpKTlVqUjNTRUZaUkZaUlVVUkZlRlo2WVZka2VtUkhPWGxhVXpGd1ltNVNiQXBqYlRGc1drZHNhR1JIVlhkSWFHTk9UV3BOZDAxcVJURk5WR3Q2VFhwTmVWZG9ZMDVOYWsxM1RXcEZNVTFVYXpCTmVrMTVWMnBCUVUxR2EzZEZkMWxJQ2t0dldrbDZhakJEUVZGWlNVdHZXa2w2YWpCRVFWRmpSRkZuUVVWV1YzSk9Na0Y1WXpOVk9EQlNRbTV4Y2taemMwTllja1pGVkdWNVRYTnJVV2hNUVZnS1lVOUJZbUZRZVd4TVlUWkhhWFZvY2xwVlJXUXJhVEpSSzJ0MmRHeFBTazQyVjNaS1lXOUphWEpIVlZWM09EUnpZMHRQUTBGdVRYZG5aMHAyVFVFMFJ3cEJNVlZrUkhkRlFpOTNVVVZCZDBsSVowUkJWRUpuVGxaSVUxVkZSRVJCUzBKblozSkNaMFZHUWxGalJFRjZRV1JDWjA1V1NGRTBSVVpuVVZWbldVNTVDa05hU0ZWd2EzcENabkZzWmxOb01pdGtWaTl1Y1djNGQwaDNXVVJXVWpCcVFrSm5kMFp2UVZVek9WQndlakZaYTBWYVlqVnhUbXB3UzBaWGFYaHBORmtLV2tRNGQySjNXVVJXVWpCU1FWRklMMEpIVlhkWk5GcG9ZVWhTTUdOSVRUWk1lVGx1WVZoU2IyUlhTWFZaTWpsMFRESjRhR1JZU214aWJsSjZZVmN4ZGdwaWFUbDNZMjA1TWxwWE5XaGliVTVzVEZjMWQySlRNVEJhV0U0d1RIazFibUZZVW05a1YwbDJaREk1ZVdFeVduTmlNMlI2VEROS2JHSkhWbWhqTWxWMUNtVlhNWE5SU0Vwc1dtNU5kbUZIVm1oYVNFMTJZbGRHY0dKcVFUVkNaMjl5UW1kRlJVRlpUeTlOUVVWQ1FrTjBiMlJJVW5kamVtOTJURE5TZG1FeVZuVUtURzFHYW1SSGJIWmliazExV2pKc01HRklWbWxrV0U1c1kyMU9kbUp1VW14aWJsRjFXVEk1ZEUxQ09FZERhWE5IUVZGUlFtYzNPSGRCVVVsRlJWaGtkZ3BqYlhSdFlrYzVNMWd5VW5Cak0wSm9aRWRPYjAxRVdVZERhWE5IUVZGUlFtYzNPSGRCVVUxRlMwUkZNbGx0Um1sYWJWcHBUMVJGTVUxNlozaE5WMVY0Q2s5VVRtcE5SRVUxVDFSTk5VMTZhM2hOZWxVelRYcGplVmxxU1RGWk1sVjNTbWRaUzB0M1dVSkNRVWRFZG5wQlFrSkJVVmxWU0ZacFlrZHNlbUZEUWxFS1dWZE9jbGxYWkd4SlNGSjJTVWMxZDJKWGNIcE5RelJIUTJselIwRlJVVUpuTnpoM1FWRlZSVWxIZUdoa1dFcHNZbTVTZW1GWE1YWmlhVGwzWTIwNU1ncGFWelZvWW0xT2JFeFhOWGRpVXpFd1dsaE9NRTFDTUVkRGFYTkhRVkZSUW1jM09IZEJVVmxGUkROS2JGcHVUWFpoUjFab1draE5kbUpYUm5CaWFrTkNDbWwzV1V0TGQxbENRa0ZJVjJWUlNVVkJaMUk1UWtoelFXVlJRak5CVGpBNVRVZHlSM2g0UlhsWmVHdGxTRXBzYms1M1MybFRiRFkwTTJwNWRDODBaVXNLWTI5QmRrdGxOazlCUVVGQ2FHeGhVbGhPVFVGQlFWRkVRVVZuZDFKblNXaEJUMXBaU0VNeVFYbENORTF0TlhWV05tVjBhV1ZuWTJSdlFqVjBMek5STmdwbE9IQmhhREpDU0RZd2RYSkJhVVZCZGpseWRqWlhUa2w1VUdaWWNsQXhlWHA1YTFGc1pIYzVhVVY0VTBKb0wySnlUazVxVkV4NlVDdDNXWGREWjFsSkNrdHZXa2w2YWpCRlFYZE5SRnAzUVhkYVFVbDNWQ3R1VDFWalIyMVVLMHN4WjNSVkwwVlVhVXBsZDFKVVdIUllOV0pxUm1nd1FVVkVWM3BXUm14TVVVc0theXREVFVOeUswTnRhRXBuWm05aVpEZ3pjWGRCYWtGNk9WZHdOQzlyY2tsbmVTdHhSRGR2WlVOM2JGVklOelJOVG1kWGNIa3lVVlUxVDNnelNqWXhkd3BRTWk4d1R6ZGlhRWcxWmtSaFIzUlpWVVpMV25wM1FUMEtMUzB0TFMxRlRrUWdRMFZTVkVsR1NVTkJWRVV0TFMwdExRbz0iLCJzaWciOiJUVVZWUTBsUlJFcGhhRlJ3VTI1c2RqWkllbFZxTW5reEwxQkNXVXhHZVRob2FFb3JOV1ZCUWxrM2RYazRVbEJ6UjFGSlowcFdkVXd6UjNJNWVXSXlWRkJWUlUxek5rbGxhVFZJVUVoaWVVZHNObWw0WjJRME1YbDJlVEEzVWxFOSJ9XX0sImhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIyYzVhZjNiZThjNzcxYzAwYzVhZGYwNDAxMzQ5YTg1NjM5NjA3Nzg4MzQwNjRhMmYyOTk5YzY4YmZiMWI0Njg4In0sInBheWxvYWRIYXNoIjp7ImFsZ29yaXRobSI6InNoYTI1NiIsInZhbHVlIjoiNjg5ZTE2NmNlM2I1Zjk5MTgxZDExYjcyYjg2OTJkODEwYjJlM2NkMTdmZWNiZjBiNzRmNDBmYTRmNmUzNjNkNSJ9fX19" + } + ], + "timestampVerificationData": null + }, + "dsseEnvelope": { + "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInN1YmplY3QiOlt7Im5hbWUiOiJwa2c6bnBtLyU0MGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QDEuMC4wIiwiZGlnZXN0Ijp7InNoYTUxMiI6IjI5ZDE5ZjI2MjMzZjQ0NDEzMjg0MTJiMzRmZDczZWQxMDRlY2ZlZjYyZjE0MDk3ODkwY2NjZjc0NTViNTIxYjY1YzVhY2ZmODUxODQ5ZmFhODVjODUzOTVhYTIyZDQwMTQzNmYwMWYzYWZiNjFiMTljNzgwZTkwNmM4OGM3ZjIwIn19XSwicHJlZGljYXRlVHlwZSI6Imh0dHBzOi8vc2xzYS5kZXYvcHJvdmVuYW5jZS92MC4yIiwicHJlZGljYXRlIjp7ImJ1aWxkVHlwZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9ucG0vY2xpL2doYUB2MSIsImJ1aWxkZXIiOnsiaWQiOiJodHRwczovL2dpdGh1Yi5jb20vbnBtL2NsaUA5LjUuMCJ9LCJpbnZvY2F0aW9uIjp7ImNvbmZpZ1NvdXJjZSI6eyJ1cmkiOiJnaXQraHR0cHM6Ly9naXRodWIuY29tL2xhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0QHJlZnMvaGVhZHMvbWFpbiIsImRpZ2VzdCI6eyJzaGExIjoiMTZiYWJmZmI5MTUzODExZTE5M2MwMTk5MzkzOTEzNTczNzJiMjVjZSJ9LCJlbnRyeVBvaW50IjoibGF1cmVudHNpbW9uL3Byb3ZlbmFuY2UtbnBtLXRlc3QvLmdpdGh1Yi93b3JrZmxvd3MvcmVsZWFzZS55bWxAcmVmcy9oZWFkcy9tYWluIn0sInBhcmFtZXRlcnMiOnt9LCJlbnZpcm9ubWVudCI6eyJHSVRIVUJfQUNUT1JfSUQiOiI2NDUwNTA5OSIsIkdJVEhVQl9FVkVOVF9OQU1FIjoid29ya2Zsb3dfZGlzcGF0Y2giLCJHSVRIVUJfUkVGIjoicmVmcy9oZWFkcy9tYWluIiwiR0lUSFVCX1JFRl9UWVBFIjoiYnJhbmNoIiwiR0lUSFVCX1JFUE9TSVRPUlkiOiJsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsIkdJVEhVQl9SRVBPU0lUT1JZX0lEIjoiNjAyMjIzOTQ1IiwiR0lUSFVCX1JFUE9TSVRPUllfT1dORVJfSUQiOiI2NDUwNTA5OSIsIkdJVEhVQl9SVU5fQVRURU1QVCI6IjEiLCJHSVRIVUJfUlVOX0lEIjoiNDE4NzQ2NDU3NyIsIkdJVEhVQl9SVU5fTlVNQkVSIjoiMiIsIkdJVEhVQl9TSEEiOiIxNmJhYmZmYjkxNTM4MTFlMTkzYzAxOTkzOTM5MTM1NzM3MmIyNWNlIiwiR0lUSFVCX1dPUktGTE9XX1JFRiI6ImxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvaGVhZHMvbWFpbiIsIkdJVEhVQl9XT1JLRkxPV19TSEEiOiIxNmJhYmZmYjkxNTM4MTFlMTkzYzAxOTkzOTM5MTM1NzM3MmIyNWNlIn19LCJtZXRhZGF0YSI6eyJidWlsZEludm9jYXRpb25JZCI6IjQxODc0NjQ1NzctMSIsImNvbXBsZXRlbmVzcyI6eyJwYXJhbWV0ZXJzIjpmYWxzZSwiZW52aXJvbm1lbnQiOmZhbHNlLCJtYXRlcmlhbHMiOmZhbHNlfSwicmVwcm9kdWNpYmxlIjpmYWxzZX0sIm1hdGVyaWFscyI6W3sidXJpIjoiZ2l0K2h0dHBzOi8vZ2l0aHViLmNvbS9sYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdCIsImRpZ2VzdCI6eyJzaGExIjoiMTZiYWJmZmI5MTUzODExZTE5M2MwMTk5MzkzOTEzNTczNzJiMjVjZSJ9fV19fQ==", + "payloadType": "application/vnd.in-toto+json", + "signatures": [ + { + "sig": "MEUCIQDJahTpSnlv6HzUj2y1/PBYLFy8hhJ+5eABY7uy8RPsGQIgJVuL3Gr9yb2TPUEMs6Iei5HPHbyGl6ixgd41yvy07RQ=", + "keyid": "" + } + ] + } + } + }, + { + "predicateType": "https://github.com/npm/attestation/tree/main/specs/publish/v0.1", + "bundle": { + "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.1", + "verificationMaterial": { + "publicKey": { + "hint": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA" + }, + "tlogEntries": [ + { + "logIndex": "13420289", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "intoto", + "version": "0.0.2" + }, + "integratedTime": "1676489615", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCICYgQbiFj7t0A9B/p4Hkq5H0gB41InPBFFnhEeuP4Fo0AiEA7fGqVACs5cFpoQGHX8HVDq/jKBWbS0gutPXpcOz6r6g=" + }, + "inclusionProof": null, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7ImtleWlkIjoiU0hBMjU2OmpsM2J3c3d1ODBQampva0NnaDBvMnc1YzJVNExoUUFFNTdnajljejFrekEiLCJwdWJsaWNLZXkiOiJMUzB0TFMxQ1JVZEpUaUJRVlVKTVNVTWdTMFZaTFMwdExTMEtUVVpyZDBWM1dVaExiMXBKZW1vd1EwRlJXVWxMYjFwSmVtb3dSRUZSWTBSUlowRkZNVTlzWWpONlRVRkdSbmhZUzBocFNXdFJUelZqU2pOWmFHdzFhVFpWVUhBclNXaDFkR1ZDU21KMVNHTkJOVlZ2WjB0dk1FVlhkR3hYZDFjMlMxTmhTMjlVVGtWWlREZEtiRU5SYVZadWEyaENhM1JWWjJjOVBRb3RMUzB0TFVWT1JDQlFWVUpNU1VNZ1MwVlpMUzB0TFMwPSIsInNpZyI6IlRVVlJRMGxETURGaFJqbFFZVWxtSzNOcVkzRlBiVzQwUVZaVU56bFBWMFJuVkZGVk5XVXZiVkp0TVcweVNIWjVRV2xCY0hCNk1FWkxWVzFEVjJwdVUyUnJORzB5VkdGTlpXMXFSRXRqUlcxTVdFSTRWVVpFTlZsYWRETTJaejA5In1dfSwiaGFzaCI6eyJhbGdvcml0aG0iOiJzaGEyNTYiLCJ2YWx1ZSI6IjkxNDU3YjdiYzg1NTgwY2Y2NTAxNDM5NDU5ZDYyOWI0YzBlOTUxNmFjNzc3NTllNGQwNzMwZjVlMTUxNjRkMDcifSwicGF5bG9hZEhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI1ZmFmZTQwMmJiYzBiMTNhMmFmMmIzMjhjYmNjNmFiZTlmZTA1MGRkNDUzNjNkNTE1YWIyYzk4MjA3NDMwNjVkIn19fX0=" + } + ], + "timestampVerificationData": null + }, + "dsseEnvelope": { + "payload": "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50QS92MC4xIiwKICAic3ViamVjdCI6IFsKICAgIHsKICAgICAgIm5hbWUiOiAicGtnOm5wbS8lNDBsYXVyZW50c2ltb24vcHJvdmVuYW5jZS1ucG0tdGVzdEAxLjAuMCIsCiAgICAgICJkaWdlc3QiOiB7CiAgICAgICAgInNoYTUxMiI6ICIyOWQxOWYyNjIzM2Y0NDQxMzI4NDEyYjM0ZmQ3M2VkMTA0ZWNmZWY2MmYxNDA5Nzg5MGNjY2Y3NDU1YjUyMWI2NWM1YWNmZjg1MTg0OWZhYTg1Yzg1Mzk1YWEyMmQ0MDE0MzZmMDFmM2FmYjYxYjE5Yzc4MGU5MDZjODhjN2YyMCIKICAgICAgfQogICAgfQogIF0sCiAgInByZWRpY2F0ZVR5cGUiOiAiaHR0cHM6Ly9naXRodWIuY29tL25wbS9hdHRlc3RhdGlvbi90cmVlL21haW4vc3BlY3MvcHVibGlzaC92MC4xIiwKICAicHJlZGljYXRlIjogewogICAgIm5hbWUiOiAiQGxhdXJlbnRzaW1vbi9wcm92ZW5hbmNlLW5wbS10ZXN0IiwKICAgICJ2ZXJzaW9uIjogIjEuMC4wIiwKICAgICJyZWdpc3RyeSI6ICJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZyIKICB9Cn0K", + "payloadType": "application/vnd.in-toto+json", + "signatures": [ + { + "sig": "MEQCIC01aF9PaIf+sjcqOmn4AVT79OWDgTQU5e/mRm1m2HvyAiAppz0FKUmCWjnSdk4m2TaMemjDKcEmLXB8UFD5YZt36g==", + "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA" + } + ] + } + } + } +] diff --git a/verifiers/internal/gha/verifier.go b/verifiers/internal/gha/verifier.go index c5ce51b..d2b8878 100644 --- a/verifiers/internal/gha/verifier.go +++ b/verifiers/internal/gha/verifier.go @@ -54,15 +54,19 @@ func verifyEnvAndCert(env *dsse.Envelope, return nil, nil, err } - // Verify the workflow identity. - builderID, err := VerifyWorkflowIdentity(workflowInfo, builderOpts, - provenanceOpts.ExpectedSourceURI, defaultBuilders) + // Verify the builder identity. + builderID, err := VerifyBuilderIdentity(workflowInfo, builderOpts, defaultBuilders) if err != nil { return nil, nil, err } + // Verify the source repository from the certificate. + if err := VerifyCertficateSourceRepository(workflowInfo, provenanceOpts.ExpectedSourceURI); err != nil { + return nil, nil, err + } + // Verify properties of the SLSA provenance. - // Unpack and verify info in the provenance, including the Subject Digest. + // Unpack and verify info in the provenance, including the subject Digest. provenanceOpts.ExpectedBuilderID = builderID.String() if err := VerifyProvenance(env, provenanceOpts); err != nil { return nil, nil, err @@ -80,6 +84,65 @@ func verifyEnvAndCert(env *dsse.Envelope, return r, builderID, nil } +func verifyNpmEnvAndCert(env *dsse.Envelope, + cert *x509.Certificate, + provenanceOpts *options.ProvenanceOpts, + builderOpts *options.BuilderOpts, + defaultBuilders map[string]bool, +) (*utils.TrustedBuilderID, error) { + /* Verify properties of the signing identity. */ + // Get the workflow info given the certificate information. + workflowInfo, err := GetWorkflowInfoFromCertificate(cert) + if err != nil { + return nil, err + } + + // Verify the workflow identity. + trustedBuilderID, err := VerifyBuilderIdentity(workflowInfo, builderOpts, defaultBuilders) + // We accept a non-trusted builder for the default npm builder + // that uses npm CLI. + if err != nil && !errors.Is(err, serrors.ErrorUntrustedReusableWorkflow) { + return nil, err + } + + // TODO(#493): retrieve certificate information to match + // with the provenance. + // Today it's not possible due to lack of information in the cert. + // Verify the source repository from the certificate. + if err := VerifyCertficateSourceRepository(workflowInfo, provenanceOpts.ExpectedSourceURI); err != nil { + return nil, err + } + + // Verify properties of the SLSA provenance. + // Unpack and verify info in the provenance, including the Subject Digest. + // WARNING: builderID may be empty if it's not a reusable builder workflow. + if trustedBuilderID != nil { + provenanceOpts.ExpectedBuilderID = trustedBuilderID.String() + } else { + if builderOpts == nil || builderOpts.ExpectedID == nil { + return nil, fmt.Errorf("builder mistmatch. No builder ID provided by user , got '%v'", builderGitHubRunnerID) + } + // TODO(#494): update the builder ID name. + trustedBuilderID, err = utils.TrustedBuilderIDNew(builderGitHubRunnerID) + if err != nil { + return nil, err + } + if err := trustedBuilderID.Matches(*builderOpts.ExpectedID, false); err != nil { + return nil, fmt.Errorf("builder mistmatch. %w", err) + } + } + + if err := VerifyNpmPackageProvenance(env, provenanceOpts); err != nil { + return nil, err + } + + fmt.Fprintf(os.Stderr, "Verified build using builder %s at commit %s\n", + trustedBuilderID.String(), + workflowInfo.CallerHash) + + return trustedBuilderID, nil +} + // VerifyArtifact verifies provenance for an artifact. func (v *GHAVerifier) VerifyArtifact(ctx context.Context, provenance []byte, artifactHash string, @@ -179,3 +242,62 @@ func (v *GHAVerifier) VerifyImage(ctx context.Context, } return nil, nil, fmt.Errorf("%w", serrors.ErrorNoValidSignature) } + +// VerifyNpmPackage verifies an npm package tarball. +func (v *GHAVerifier) VerifyNpmPackage(ctx context.Context, + attestations []byte, tarballHash string, + provenanceOpts *options.ProvenanceOpts, + builderOpts *options.BuilderOpts, +) ([]byte, *utils.TrustedBuilderID, error) { + trustedRoot, err := GetTrustedRoot(ctx) + if err != nil { + return nil, nil, err + } + + npm, err := NpmNew(ctx, trustedRoot, attestations) + if err != nil { + return nil, nil, err + } + + // Verify provenance signature. + if err := npm.verifyProvenanceAttestationSignature(); err != nil { + return nil, nil, err + } + + // Verify publish attesttation signature. + if err := npm.verifyPublishAttesttationSignature(); err != nil { + return nil, nil, err + } + + // Verify attestation headers. + if err := npm.verifyIntotoHeaders(); err != nil { + return nil, nil, err + } + + // Verify package names match. + if provenanceOpts != nil { + if err := npm.verifyPackageName(provenanceOpts.ExpectedPackageName); err != nil { + return nil, nil, err + } + + if err := npm.verifyPackageVersion(provenanceOpts.ExpectedPackageVersion); err != nil { + return nil, nil, err + } + } + + // Verify certificate information. + builder, err := verifyNpmEnvAndCert(npm.ProvenanceEnvelope(), + npm.ProvenanceLeafCertificate(), + provenanceOpts, builderOpts, + defaultBYOBReusableWorkflows) + if err != nil { + return nil, nil, err + } + + prov, err := npm.verifiedProvenanceBytes() + if err != nil { + return nil, nil, err + } + + return prov, builder, nil +} diff --git a/verifiers/utils/dsse.go b/verifiers/utils/dsse.go new file mode 100644 index 0000000..d839d63 --- /dev/null +++ b/verifiers/utils/dsse.go @@ -0,0 +1,45 @@ +package utils + +import ( + "encoding/base64" + "fmt" + + dsselib "github.com/secure-systems-lab/go-securesystemslib/dsse" + serrors "github.com/slsa-framework/slsa-verifier/v2/errors" +) + +func PayloadFromEnvelope(env *dsselib.Envelope) ([]byte, error) { + payload, err := base64.StdEncoding.DecodeString(env.Payload) + if err != nil { + return nil, fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, err.Error()) + } + if payload == nil { + return nil, fmt.Errorf("%w: empty payload", serrors.ErrorInvalidFormat) + } + return payload, nil +} + +func DecodeSignature(s string) ([]byte, error) { + var errs []error + // First try the std decoding. + rsig, err := base64.StdEncoding.DecodeString(s) + if err == nil { + // No error, return the value. + return rsig, nil + } + errs = append(errs, err) + + // If std decoding failed, try URL decoding. + // We try both because we encountered decoding failures + // during our tests. The DSSE documentation does not prescribe + // which encoding to use: `Either standard or URL-safe encoding is allowed`. + // https://github.com/secure-systems-lab/dsse/blob/27ce241dec575998dee8967c3c76d4edd5d6ee73/envelope.md#standard-json-envelope. + rsig, err = base64.URLEncoding.DecodeString(s) + if err == nil { + // No error, return the value. + return rsig, nil + } + errs = append(errs, err) + + return nil, fmt.Errorf("%w: %v", serrors.ErrorInvalidEncoding, errs) +} diff --git a/verifiers/utils/dsse_test.go b/verifiers/utils/dsse_test.go new file mode 100644 index 0000000..70d6bc3 --- /dev/null +++ b/verifiers/utils/dsse_test.go @@ -0,0 +1,55 @@ +package utils + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + + serrors "github.com/slsa-framework/slsa-verifier/v2/errors" +) + +func Test_DecodeSignature(t *testing.T) { + t.Parallel() + tests := []struct { + name string + encoded string + decoded string + expected error + }{ + { + name: "std encoding", + encoded: "YWJjMTIzIT8kKiYoKSctPUB+", + decoded: "abc123!?$*&()'-=@~", + }, + { + name: "URL encoding", + encoded: "YWJjMTIzIT8kKiYoKSctPUB-", + decoded: "abc123!?$*&()'-=@~", + }, + { + name: "invalid", + encoded: "invalid encoding", + expected: serrors.ErrorInvalidEncoding, + }, + } + + for _, tt := range tests { + tt := tt // Re-initializing variable so it is not changed while executing the closure below + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + c, err := DecodeSignature(tt.encoded) + if !cmp.Equal(err, tt.expected, cmpopts.EquateErrors()) { + t.Errorf(cmp.Diff(err, tt.expected, cmpopts.EquateErrors())) + } + if err != nil { + return + } + cs := string(c) + if cs != tt.decoded { + t.Errorf(cmp.Diff(cs, tt.decoded)) + } + }) + } +} diff --git a/verifiers/verifier.go b/verifiers/verifier.go index e8ce53f..f131e89 100644 --- a/verifiers/verifier.go +++ b/verifiers/verifier.go @@ -61,3 +61,17 @@ func VerifyArtifact(ctx context.Context, return verifier.VerifyArtifact(ctx, provenance, artifactHash, provenanceOpts, builderOpts) } + +func VerifyNpmPackage(ctx context.Context, + attestations []byte, tarballHash string, + provenanceOpts *options.ProvenanceOpts, + builderOpts *options.BuilderOpts, +) ([]byte, *utils.TrustedBuilderID, error) { + verifier, err := getVerifier(builderOpts) + if err != nil { + return nil, nil, err + } + + return verifier.VerifyNpmPackage(ctx, attestations, tarballHash, + provenanceOpts, builderOpts) +}