Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add GHSA-vfp6-jrw2-99g9 fixes in cosign v1.13.1 #1

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/kind-verify-attestation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:

env:
KO_DOCKER_REPO: "registry.local:5000/policy-controller"
SCAFFOLDING_RELEASE_VERSION: "v0.4.8"
SCAFFOLDING_RELEASE_VERSION: "v0.6.8"
GO111MODULE: on
GOFLAGS: -ldflags=-s -ldflags=-w
KOCACHE: ~/ko
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,9 @@ ko-sget:
.PHONY: ko-local
ko-local:
$(create_kocache_path)
LDFLAGS="$(LDFLAGS)" GIT_HASH=$(GIT_HASH) GIT_VERSION=$(GIT_VERSION) \
KO_DOCKER_REPO=ko.local LDFLAGS="$(LDFLAGS)" GIT_HASH=$(GIT_HASH) GIT_VERSION=$(GIT_VERSION) \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice find!

KOCACHE=$(KOCACHE_PATH) ko build --base-import-paths \
--tags $(GIT_VERSION) --tags $(GIT_HASH) --local \
--tags $(GIT_VERSION) --tags $(GIT_HASH) \
$(ARTIFACT_HUB_LABELS) \
github.com/sigstore/cosign/cmd/cosign

Expand Down
10 changes: 10 additions & 0 deletions pkg/cosign/fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import (
"golang.org/x/sync/errgroup"
)

const maxAllowedSigsOrAtts = 100

type SignedPayload struct {
Base64Signature string
Payload []byte
Expand Down Expand Up @@ -78,6 +80,10 @@ func FetchSignaturesForReference(ctx context.Context, ref name.Reference, opts .
return nil, fmt.Errorf("no signatures associated with %s", ref)
}

if len(l) > maxAllowedSigsOrAtts {
return nil, fmt.Errorf("maximum number of signatures on an image is %d, found %d", maxAllowedSigsOrAtts, len(l))
}

signatures := make([]SignedPayload, len(l))
var g errgroup.Group
g.SetLimit(runtime.NumCPU())
Expand Down Expand Up @@ -130,6 +136,10 @@ func FetchAttestationsForReference(ctx context.Context, ref name.Reference, opts
return nil, fmt.Errorf("no attestations associated with %s", ref)
}

if len(l) > maxAllowedSigsOrAtts {
return nil, fmt.Errorf("maximum number of attestations on an image is %d, found %d", maxAllowedSigsOrAtts, len(l))
}

attestations := make([]AttestationPayload, len(l))
var g errgroup.Group
g.SetLimit(runtime.NumCPU())
Expand Down
104 changes: 104 additions & 0 deletions test/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,81 @@ func TestAttestationReplaceCreate(t *testing.T) {
}
}

func TestExcessiveAttestations(t *testing.T) {
repo, stop := reg(t)
defer stop()
td := t.TempDir()

imgName := path.Join(repo, "cosign-attest-download-e2e")

_, _, cleanup := mkimage(t, imgName)
defer cleanup()

_, privKeyPath, _ := keypair(t, td)
ko := options.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc}

ctx := context.Background()

slsaAttestation := `{ "buildType": "x", "builder": { "id": "2" }, "recipe": {} }`
slsaAttestationPath := filepath.Join(td, "attestation.slsa.json")
if err := os.WriteFile(slsaAttestationPath, []byte(slsaAttestation), 0600); err != nil {
t.Fatal(err)
}

vulnAttestation := `
{
"invocation": {
"parameters": null,
"uri": "invocation.example.com/cosign-testing",
"event_id": "",
"builder.id": ""
},
"scanner": {
"uri": "fakescanner.example.com/cosign-testing",
"version": "",
"db": {
"uri": "",
"version": ""
},
"result": null
},
"metadata": {
"scanStartedOn": "2022-04-12T00:00:00Z",
"scanFinishedOn": "2022-04-12T00:10:00Z"
}
}
`
ref, err := name.ParseReference(imgName)
if err != nil {
t.Fatal(err)
}
regOpts := options.RegistryOptions{}
ociremoteOpts, err := regOpts.ClientOpts(ctx)
if err != nil {
t.Fatal(err)
}

for i := 0; i < 102; i++ {
vulnAttestationPath := filepath.Join(td, fmt.Sprintf("attestation-%d.vuln.json", i))
if err := os.WriteFile(vulnAttestationPath, []byte(vulnAttestation), 0600); err != nil {
t.Fatal(err)
}

// Attest again with replace=true, replacing the previous attestation
must(attest.AttestCmd(ctx, ko, options.RegistryOptions{}, imgName, "", "", false, vulnAttestationPath, false,
"vuln", false, 30*time.Second, false), t)
}

_, err = cosign.FetchAttestationsForReference(ctx, ref, ociremoteOpts...)
if err == nil {
t.Fatalf("Expected an error, but 'err' was 'nil'")
}
expectedError := "maximum number of attestations on an image is 100, found 102"
if err.Error() != expectedError {
t.Errorf("Exted the error to be: '%s' but it was '%s'", expectedError, err.Error())
}
}

func TestAttestationReplace(t *testing.T) {
repo, stop := reg(t)
defer stop()
Expand Down Expand Up @@ -505,6 +580,35 @@ func TestDuplicateSign(t *testing.T) {
}
}

func TestExcessiveSignatures(t *testing.T) {
repo, stop := reg(t)
defer stop()
td := t.TempDir()

imgName := path.Join(repo, "cosign-e2e")

_, _, cleanup := mkimage(t, imgName)
defer cleanup()

ctx := context.Background()

for i := 0; i < 102; i++ {
_, privKeyPath, _ := keypair(t, td)

// Sign the image
ko := options.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc}
must(sign.SignCmd(ro, ko, options.RegistryOptions{}, nil, []string{imgName}, "", "", true, "", "", "", false, false, "", false), t)
}
err := download.SignatureCmd(ctx, options.RegistryOptions{}, imgName)
if err == nil {
t.Fatal("Expected an error, but 'err' was 'nil'")
}
expectedErr := "maximum number of signatures on an image is 100, found 102"
if err.Error() != expectedErr {
t.Fatalf("Expected the error '%s', but got the error '%s'", expectedErr, err.Error())
}
}

func TestKeyURLVerify(t *testing.T) {
// TODO: re-enable once distroless images are being signed by the new client
t.Skip()
Expand Down
Loading