Skip to content

Commit ea92927

Browse files
cpanatoAdamKorczcodysoylandhaydentherapper
authored
* Merge pull request from GHSA-vfp6-jrw2-99g9 * Add limit to number of sigs and attestations Signed-off-by: AdamKorcz <44787359+AdamKorcz@users.noreply.github.com> * Update pkg/cosign/fetch.go Co-authored-by: Cody Soyland <codysoyland@gmail.com> Signed-off-by: AdamKorcz <44787359+AdamKorcz@users.noreply.github.com> * Update error message Signed-off-by: Hayden B <hblauzvern@google.com> * fix compilation error Signed-off-by: Hayden Blauzvern <hblauzvern@google.com> * Add e2e tests Signed-off-by: Hayden Blauzvern <hblauzvern@google.com> --------- Signed-off-by: AdamKorcz <44787359+AdamKorcz@users.noreply.github.com> Signed-off-by: Hayden B <hblauzvern@google.com> Signed-off-by: Hayden Blauzvern <hblauzvern@google.com> Co-authored-by: Cody Soyland <codysoyland@gmail.com> Co-authored-by: Hayden B <hblauzvern@google.com> * fix missing import Signed-off-by: cpanato <ctadeu@gmail.com> * bump golang to 1.19.13 Signed-off-by: cpanato <ctadeu@gmail.com> * update tests Signed-off-by: cpanato <ctadeu@gmail.com> * refactor validate release Signed-off-by: cpanato <ctadeu@gmail.com> * pin sigstore/scaffolding/actions/setup to v0.4.13 Signed-off-by: cpanato <ctadeu@gmail.com> * update ko-local Signed-off-by: cpanato <ctadeu@gmail.com> --------- Signed-off-by: AdamKorcz <44787359+AdamKorcz@users.noreply.github.com> Signed-off-by: Hayden B <hblauzvern@google.com> Signed-off-by: Hayden Blauzvern <hblauzvern@google.com> Signed-off-by: cpanato <ctadeu@gmail.com> Co-authored-by: AdamKorcz <44787359+AdamKorcz@users.noreply.github.com> Co-authored-by: Cody Soyland <codysoyland@gmail.com> Co-authored-by: Hayden B <hblauzvern@google.com>
1 parent d862088 commit ea92927

File tree

6 files changed

+209
-41
lines changed

6 files changed

+209
-41
lines changed

.github/workflows/kind-verify-attestation.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ jobs:
6464
make cosign
6565
6666
- name: Install cluster + sigstore
67-
uses: sigstore/scaffolding/actions/setup@main
67+
uses: sigstore/scaffolding/actions/setup@v0.4.13
6868
with:
6969
legacy-variables: "false"
7070
k8s-version: ${{ matrix.k8s-version }}

.github/workflows/validate-release.yml

Lines changed: 84 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -20,55 +20,104 @@ on:
2020
branches:
2121
- main
2222
- release-*
23-
- 1.0-fork
2423
pull_request:
2524

2625
jobs:
26+
check-signature:
27+
runs-on: ubuntu-latest
28+
container:
29+
image: gcr.io/projectsigstore/cosign:v1.13.1@sha256:fd5b09be23ef1027e1bdd490ce78dcc65d2b15902e1f4ba8e04f3b4019cc1057
30+
31+
steps:
32+
- name: Check Signature
33+
run: |
34+
cosign verify ghcr.io/gythialy/golang-cross:v1.19.13-0@sha256:06e3605b227948431d43f4a868b68d4a771c71c728099f37856e404f2d77cf06
35+
env:
36+
TUF_ROOT: /tmp
37+
COSIGN_EXPERIMENTAL: true
38+
2739
validate-release-job:
2840
runs-on: ubuntu-latest
41+
needs:
42+
- check-signature
2943

30-
permissions:
31-
actions: none
32-
checks: none
33-
contents: none
34-
deployments: none
35-
issues: none
36-
packages: none
37-
pull-requests: none
38-
repository-projects: none
39-
security-events: none
40-
statuses: none
44+
container:
45+
image: ghcr.io/gythialy/golang-cross:v1.19.13-0@sha256:06e3605b227948431d43f4a868b68d4a771c71c728099f37856e404f2d77cf06
4146

42-
env:
43-
CROSS_BUILDER_IMAGE: ghcr.io/gythialy/golang-cross:v1.19.4-0@sha256:53ee894818ac14377996a6fe7c8fe6156d018a20f82aaf69f2519fc45d897bec
44-
COSIGN_IMAGE: gcr.io/projectsigstore/cosign:v1.13.1@sha256:fd5b09be23ef1027e1bdd490ce78dcc65d2b15902e1f4ba8e04f3b4019cc1057
47+
permissions: {}
4548

4649
steps:
47-
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.0.2
50+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
4851

49-
- name: Check Signature
52+
# Error: fatal: detected dubious ownership in repository at '/__w/cosign/cosign'
53+
# To add an exception for this directory, call:
54+
# git config --system --add safe.directory /__w/cosign/cosign
55+
# Reason: Recent versions of git require the .git folder to be owned
56+
# by the same user (see https://github.blog/2022-04-12-git-security-vulnerability-announced/).
57+
# Related
58+
# - https://github.com/actions/runner/issues/2033
59+
# - https://github.com/actions/checkout/issues/1048
60+
# - https://github.com/actions/runner-images/issues/6775
61+
- run: git config --system --add safe.directory /__w/cosign/cosign
62+
63+
# Related to https://github.com/sigstore/cosign/issues/3149
64+
- name: free up disk space for the release
5065
run: |
51-
docker run --rm \
52-
-e COSIGN_EXPERIMENTAL=true \
53-
-e TUF_ROOT=/tmp \
54-
$COSIGN_IMAGE \
55-
verify \
56-
$CROSS_BUILDER_IMAGE
66+
rm -rf /usr/share/dotnet/
67+
rm -rf "$AGENT_TOOLSDIRECTORY"
68+
rm -rf "/usr/local/share/boost"
69+
rm -rf /opt/ghc
70+
docker rmi $(docker image ls -aq) || true
71+
swapoff /swapfile || true
72+
rm -rf /swapfile /usr/share/dotnet /usr/local/lib/android /opt/ghc || true
73+
apt purge aria2 ansible hhvm mono-devel azure-cli shellcheck rpm xorriso zsync \
74+
clang-6.0 lldb-6.0 lld-6.0 clang-format-6.0 clang-8 lldb-8 lld-8 clang-format-8 \
75+
clang-9 lldb-9 lld-9 clangd-9 clang-format-9 dotnet-sdk-3.0 dotnet-sdk-3.1=3.1.101-1 \
76+
esl-erlang firefox g++-8 g++-9 gfortran-8 gfortran-9 google-chrome-stable \
77+
google-cloud-sdk ghc-8.0.2 ghc-8.2.2 ghc-8.4.4 ghc-8.6.2 ghc-8.6.3 ghc-8.6.4 \
78+
ghc-8.6.5 ghc-8.8.1 ghc-8.8.2 ghc-8.8.3 ghc-8.10.1 cabal-install-2.0 cabal-install-2.2 \
79+
cabal-install-2.4 cabal-install-3.0 cabal-install-3.2 heroku imagemagick \
80+
libmagickcore-dev libmagickwand-dev libmagic-dev ant ant-optional kubectl \
81+
mercurial apt-transport-https mono-complete mysql-client libmysqlclient-dev \
82+
mysql-server mssql-tools unixodbc-dev yarn bazel chrpath libssl-dev libxft-dev \
83+
libfreetype6 libfreetype6-dev libfontconfig1 libfontconfig1-dev php7.1 php7.1-bcmath \
84+
php7.1-bz2 php7.1-cgi php7.1-cli php7.1-common php7.1-curl php7.1-dba php7.1-dev \
85+
php7.1-enchant php7.1-fpm php7.1-gd php7.1-gmp php7.1-imap php7.1-interbase php7.1-intl \
86+
php7.1-json php7.1-ldap php7.1-mbstring php7.1-mcrypt php7.1-mysql php7.1-odbc \
87+
php7.1-opcache php7.1-pgsql php7.1-phpdbg php7.1-pspell php7.1-readline php7.1-recode \
88+
php7.1-snmp php7.1-soap php7.1-sqlite3 php7.1-sybase php7.1-tidy php7.1-xml \
89+
php7.1-xmlrpc php7.1-xsl php7.1-zip php7.2 php7.2-bcmath php7.2-bz2 php7.2-cgi \
90+
php7.2-cli php7.2-common php7.2-curl php7.2-dba php7.2-dev php7.2-enchant php7.2-fpm \
91+
php7.2-gd php7.2-gmp php7.2-imap php7.2-interbase php7.2-intl php7.2-json php7.2-ldap \
92+
php7.2-mbstring php7.2-mysql php7.2-odbc php7.2-opcache php7.2-pgsql php7.2-phpdbg \
93+
php7.2-pspell php7.2-readline php7.2-recode php7.2-snmp php7.2-soap php7.2-sqlite3 \
94+
php7.2-sybase php7.2-tidy php7.2-xml php7.2-xmlrpc php7.2-xsl php7.2-zip php7.3 \
95+
php7.3-bcmath php7.3-bz2 php7.3-cgi php7.3-cli php7.3-common php7.3-curl php7.3-dba \
96+
php7.3-dev php7.3-enchant php7.3-fpm php7.3-gd php7.3-gmp php7.3-imap php7.3-interbase \
97+
php7.3-intl php7.3-json php7.3-ldap php7.3-mbstring php7.3-mysql php7.3-odbc \
98+
php7.3-opcache php7.3-pgsql php7.3-phpdbg php7.3-pspell php7.3-readline php7.3-recode \
99+
php7.3-snmp php7.3-soap php7.3-sqlite3 php7.3-sybase php7.3-tidy php7.3-xml \
100+
php7.3-xmlrpc php7.3-xsl php7.3-zip php7.4 php7.4-bcmath php7.4-bz2 php7.4-cgi \
101+
php7.4-cli php7.4-common php7.4-curl php7.4-dba php7.4-dev php7.4-enchant php7.4-fpm \
102+
php7.4-gd php7.4-gmp php7.4-imap php7.4-interbase php7.4-intl php7.4-json php7.4-ldap \
103+
php7.4-mbstring php7.4-mysql php7.4-odbc php7.4-opcache php7.4-pgsql php7.4-phpdbg \
104+
php7.4-pspell php7.4-readline php7.4-snmp php7.4-soap php7.4-sqlite3 php7.4-sybase \
105+
php7.4-tidy php7.4-xml php7.4-xmlrpc php7.4-xsl php7.4-zip php-amqp php-apcu \
106+
php-igbinary php-memcache php-memcached php-mongodb php-redis php-xdebug \
107+
php-zmq snmp pollinate libpq-dev postgresql-client powershell ruby-full \
108+
sphinxsearch subversion mongodb-org -yq >/dev/null 2>&1 || true
109+
apt-get remove -y 'php.*' || true
110+
apt-get autoremove -y >/dev/null 2>&1 || true
111+
apt-get autoclean -y >/dev/null 2>&1 || true
112+
- name: check disk space
113+
run: df -h
57114

58115
- name: goreleaser snapshot
59-
run: |
60-
docker run --rm --privileged \
61-
-e PROJECT_ID=honk-fake-project \
62-
-e CI=$CI \
63-
-e RUNTIME_IMAGE=gcr.io/distroless/static:debug-nonroot \
64-
-v ${PWD}:/go/src/sigstore/cosign \
65-
-v /var/run/docker.sock:/var/run/docker.sock \
66-
-w /go/src/sigstore/cosign \
67-
--entrypoint="" \
68-
$CROSS_BUILDER_IMAGE \
69-
make snapshot
116+
run: make snapshot
117+
env:
118+
PROJECT_ID: honk-fake-project
119+
RUNTIME_IMAGE: gcr.io/distroless/static:debug-nonroot
70120

71121
- name: check binaries
72122
run: |
73123
./dist/cosign-linux-amd64 version
74-
./dist/sget-linux-amd64 version

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,9 @@ ko-sget:
148148
.PHONY: ko-local
149149
ko-local:
150150
$(create_kocache_path)
151-
LDFLAGS="$(LDFLAGS)" GIT_HASH=$(GIT_HASH) GIT_VERSION=$(GIT_VERSION) \
151+
KO_DOCKER_REPO=ko.local LDFLAGS="$(LDFLAGS)" GIT_HASH=$(GIT_HASH) GIT_VERSION=$(GIT_VERSION) \
152152
KOCACHE=$(KOCACHE_PATH) ko build --base-import-paths \
153-
--tags $(GIT_VERSION) --tags $(GIT_HASH) --local \
153+
--tags $(GIT_VERSION) --tags $(GIT_HASH) \
154154
$(ARTIFACT_HUB_LABELS) \
155155
github.com/sigstore/cosign/cmd/cosign
156156

pkg/cosign/fetch.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"context"
2020
"crypto/x509"
2121
"encoding/json"
22+
"errors"
2223
"fmt"
2324
"os"
2425
"runtime"
@@ -29,6 +30,8 @@ import (
2930
"golang.org/x/sync/errgroup"
3031
)
3132

33+
const maxAllowedSigsOrAtts = 100
34+
3235
type SignedPayload struct {
3336
Base64Signature string
3437
Payload []byte
@@ -77,6 +80,9 @@ func FetchSignaturesForReference(ctx context.Context, ref name.Reference, opts .
7780
if len(l) == 0 {
7881
return nil, fmt.Errorf("no signatures associated with %s", ref)
7982
}
83+
if len(l) > maxAllowedSigsOrAtts {
84+
return nil, fmt.Errorf("maximum number of signatures on an image is %d, found %d", maxAllowedSigsOrAtts, len(l))
85+
}
8086

8187
signatures := make([]SignedPayload, len(l))
8288
var g errgroup.Group
@@ -129,6 +135,10 @@ func FetchAttestationsForReference(ctx context.Context, ref name.Reference, opts
129135
if len(l) == 0 {
130136
return nil, fmt.Errorf("no attestations associated with %s", ref)
131137
}
138+
if len(l) > maxAllowedSigsOrAtts {
139+
errMsg := fmt.Sprintf("maximum number of attestations on an image is %d, found %d", maxAllowedSigsOrAtts, len(l))
140+
return nil, errors.New(errMsg)
141+
}
132142

133143
attestations := make([]AttestationPayload, len(l))
134144
var g errgroup.Group

release/cloudbuild.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ steps:
3939
- TUF_ROOT=/tmp
4040
args:
4141
- 'verify'
42-
- 'ghcr.io/gythialy/golang-cross:v1.19.4-0@sha256:53ee894818ac14377996a6fe7c8fe6156d018a20f82aaf69f2519fc45d897bec'
42+
- 'ghcr.io/gythialy/golang-cross:v1.19.13-0@sha256:06e3605b227948431d43f4a868b68d4a771c71c728099f37856e404f2d77cf06'
4343

4444
# maybe we can build our own image and use that to be more in a safe side
45-
- name: ghcr.io/gythialy/golang-cross:v1.19.4-0@sha256:53ee894818ac14377996a6fe7c8fe6156d018a20f82aaf69f2519fc45d897bec
45+
- name: ghcr.io/gythialy/golang-cross:v1.19.13-0@sha256:06e3605b227948431d43f4a868b68d4a771c71c728099f37856e404f2d77cf06
4646
entrypoint: /bin/sh
4747
dir: "go/src/sigstore/cosign"
4848
env:
@@ -65,7 +65,7 @@ steps:
6565
gcloud auth configure-docker \
6666
&& make release
6767
68-
- name: ghcr.io/gythialy/golang-cross:v1.19.4-0@sha256:53ee894818ac14377996a6fe7c8fe6156d018a20f82aaf69f2519fc45d897bec
68+
- name: ghcr.io/gythialy/golang-cross:v1.19.13-0@sha256:06e3605b227948431d43f4a868b68d4a771c71c728099f37856e404f2d77cf06
6969
entrypoint: 'bash'
7070
dir: "go/src/sigstore/cosign"
7171
env:

test/e2e_test.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,83 @@ func TestAttestationReplaceCreate(t *testing.T) {
373373
}
374374
}
375375

376+
func TestExcessiveAttestations(t *testing.T) {
377+
// skipping tst it is falky and taking too long
378+
t.Skip()
379+
repo, stop := reg(t)
380+
defer stop()
381+
td := t.TempDir()
382+
383+
imgName := path.Join(repo, "cosign-attest-download-e2e")
384+
385+
_, _, cleanup := mkimage(t, imgName)
386+
defer cleanup()
387+
388+
_, privKeyPath, _ := keypair(t, td)
389+
ko := options.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc}
390+
391+
ctx := context.Background()
392+
393+
slsaAttestation := `{ "buildType": "x", "builder": { "id": "2" }, "recipe": {} }`
394+
slsaAttestationPath := filepath.Join(td, "attestation.slsa.json")
395+
if err := os.WriteFile(slsaAttestationPath, []byte(slsaAttestation), 0600); err != nil {
396+
t.Fatal(err)
397+
}
398+
399+
vulnAttestation := `
400+
{
401+
"invocation": {
402+
"parameters": null,
403+
"uri": "invocation.example.com/cosign-testing",
404+
"event_id": "",
405+
"builder.id": ""
406+
},
407+
"scanner": {
408+
"uri": "fakescanner.example.com/cosign-testing",
409+
"version": "",
410+
"db": {
411+
"uri": "",
412+
"version": ""
413+
},
414+
"result": null
415+
},
416+
"metadata": {
417+
"scanStartedOn": "2022-04-12T00:00:00Z",
418+
"scanFinishedOn": "2022-04-12T00:10:00Z"
419+
}
420+
}
421+
`
422+
ref, err := name.ParseReference(imgName)
423+
if err != nil {
424+
t.Fatal(err)
425+
}
426+
regOpts := options.RegistryOptions{}
427+
ociremoteOpts, err := regOpts.ClientOpts(ctx)
428+
if err != nil {
429+
t.Fatal(err)
430+
}
431+
432+
for i := 0; i < 102; i++ {
433+
vulnAttestationPath := filepath.Join(td, fmt.Sprintf("attestation-%d.vuln.json", i))
434+
if err := os.WriteFile(vulnAttestationPath, []byte(vulnAttestation), 0600); err != nil {
435+
t.Fatal(err)
436+
}
437+
438+
// Attest to create a vuln attestation
439+
must(attest.AttestCmd(ctx, ko, options.RegistryOptions{}, imgName, "", "", false, vulnAttestationPath, false,
440+
"vuln", false, 30*time.Second, false), t)
441+
}
442+
443+
_, err = cosign.FetchAttestationsForReference(ctx, ref, ociremoteOpts...)
444+
if err == nil {
445+
t.Fatalf("Expected an error, but 'err' was 'nil'")
446+
}
447+
expectedError := "maximum number of attestations on an image is 100, found 102"
448+
if err.Error() != expectedError {
449+
t.Errorf("Exted the error to be: '%s' but it was '%s'", expectedError, err.Error())
450+
}
451+
}
452+
376453
func TestAttestationReplace(t *testing.T) {
377454
repo, stop := reg(t)
378455
defer stop()
@@ -523,6 +600,38 @@ func TestDuplicateSign(t *testing.T) {
523600
}
524601
}
525602

603+
func TestExcessiveSignatures(t *testing.T) {
604+
repo, stop := reg(t)
605+
defer stop()
606+
td := t.TempDir()
607+
608+
imgName := path.Join(repo, "cosign-e2e")
609+
610+
_, _, cleanup := mkimage(t, imgName)
611+
defer cleanup()
612+
613+
ctx := context.Background()
614+
615+
for i := 0; i < 102; i++ {
616+
_, privKeyPath, _ := keypair(t, td)
617+
618+
// Sign the image
619+
ko := options.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc}
620+
so := options.SignOptions{
621+
Upload: true,
622+
}
623+
must(sign.SignCmd(ro, ko, so, []string{imgName}), t)
624+
}
625+
err := download.SignatureCmd(ctx, options.RegistryOptions{}, imgName)
626+
if err == nil {
627+
t.Fatal("Expected an error, but 'err' was 'nil'")
628+
}
629+
expectedErr := "maximum number of signatures on an image is 100, found 102"
630+
if err.Error() != expectedErr {
631+
t.Fatalf("Expected the error '%s', but got the error '%s'", expectedErr, err.Error())
632+
}
633+
}
634+
526635
func TestKeyURLVerify(t *testing.T) {
527636
// TODO: re-enable once distroless images are being signed by the new client
528637
t.Skip()

0 commit comments

Comments
 (0)