-
Notifications
You must be signed in to change notification settings - Fork 548
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Merge pull request from GHSA-95pr-fxf5-86gv An Image may come from an untrusted source and contain an unknown number of signatures in the .sig manifest. A common pattern in cosign is to use the number of signatures as the capacity for a new slice. But this means the size of the slice is based on an unvalidated external input and could result in cosign running out of memory. This change adds validation for certain implementations of the oci.Signatures Get() method to limit the number of image descriptors returned. This way, callers can rely on the returned slice of signatures being a reasonable size to process safely. The limit is set to 1000, which is a generous size based on the practical restrictions that container registries set for image manifest size and approximations of memory allocations for signature layers. Signed-off-by: Colleen Murphy <[email protected]> * Merge pull request from GHSA-88jx-383q-w4qc When downloading an attestation or SBOM from an external source, check its size before reading it into memory. This protects the host from potentially reading a maliciously large attachment into memory and exhausting the system. SBOMs can vary widely in size, and there could be legitimate SBOMs of up to 700MB. However, reading a 700MB SBOM into memory would easily bring down a small cloud VM. Moreover, most SBOMs are not going to be that large. This change sets a reasonable default of 128MiB, and allows overriding the default by setting the environment variable `COSIGN_MAX_ATTACHMENT_SIZE`. Signed-off-by: Colleen Murphy <[email protected]> --------- Signed-off-by: Colleen Murphy <[email protected]>
- Loading branch information
1 parent
302aee6
commit 629f5f8
Showing
22 changed files
with
657 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// Copyright 2024 The Sigstore 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 | ||
// | ||
// http://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 payload | ||
|
||
import "fmt" | ||
|
||
// MaxLayerSizeExceeded is an error indicating that the layer is too big to read into memory and cosign should abort processing it. | ||
type MaxLayerSizeExceeded struct { | ||
value uint64 | ||
maximum uint64 | ||
} | ||
|
||
func NewMaxLayerSizeExceeded(value, maximum uint64) *MaxLayerSizeExceeded { | ||
return &MaxLayerSizeExceeded{value, maximum} | ||
} | ||
|
||
func (e *MaxLayerSizeExceeded) Error() string { | ||
return fmt.Sprintf("size of layer (%d) exceeded the limit (%d)", e.value, e.maximum) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// Copyright 2024 The Sigstore 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 | ||
// | ||
// http://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 payload | ||
|
||
import ( | ||
"github.com/dustin/go-humanize" | ||
"github.com/sigstore/cosign/v2/pkg/cosign/env" | ||
) | ||
|
||
const defaultMaxSize = uint64(134217728) // 128MiB | ||
|
||
func CheckSize(size uint64) error { | ||
maxSize := defaultMaxSize | ||
maxSizeOverride, exists := env.LookupEnv(env.VariableMaxAttachmentSize) | ||
if exists { | ||
var err error | ||
maxSize, err = humanize.ParseBytes(maxSizeOverride) | ||
if err != nil { | ||
maxSize = defaultMaxSize | ||
} | ||
} | ||
if size > maxSize { | ||
return NewMaxLayerSizeExceeded(size, maxSize) | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
// Copyright 2024 The Sigstore 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 | ||
// | ||
// http://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 payload | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
func TestCheckSize(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
input uint64 | ||
setting string | ||
wantErr bool | ||
}{ | ||
{ | ||
name: "size is within default limit", | ||
input: 1000, | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "size exceeds default limit", | ||
input: 200000000, | ||
wantErr: true, | ||
}, | ||
{ | ||
name: "size is within overridden limit (bytes)", | ||
input: 1000, | ||
setting: "1024", | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "size is exceeds overridden limit (bytes)", | ||
input: 2000, | ||
setting: "1024", | ||
wantErr: true, | ||
}, | ||
{ | ||
name: "size is within overridden limit (megabytes, short form)", | ||
input: 1999999, | ||
setting: "2M", | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "size exceeds overridden limit (megabytes, short form)", | ||
input: 2000001, | ||
setting: "2M", | ||
wantErr: true, | ||
}, | ||
{ | ||
name: "size is within overridden limit (megabytes, long form)", | ||
input: 1999999, | ||
setting: "2MB", | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "size exceeds overridden limit (megabytes, long form)", | ||
input: 2000001, | ||
setting: "2MB", | ||
wantErr: true, | ||
}, | ||
{ | ||
name: "size is within overridden limit (mebibytes)", | ||
input: 2097151, | ||
setting: "2MiB", | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "size exceeds overridden limit (mebibytes)", | ||
input: 2097153, | ||
setting: "2MiB", | ||
wantErr: true, | ||
}, | ||
{ | ||
name: "size is negative results in default", | ||
input: 5121, | ||
setting: "-5KiB", | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "invalid setting results in default", | ||
input: 5121, | ||
setting: "five kilobytes", | ||
wantErr: false, | ||
}, | ||
} | ||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
if test.setting != "" { | ||
t.Setenv("COSIGN_MAX_ATTACHMENT_SIZE", test.setting) | ||
} | ||
got := CheckSize(test.input) | ||
if (got != nil) != (test.wantErr) { | ||
t.Errorf("CheckSize() = %v, expected %v", got, test.wantErr) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// Copyright 2024 The Sigstore 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 | ||
// | ||
// http://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 oci | ||
|
||
import "fmt" | ||
|
||
// MaxLayersExceeded is an error indicating that the artifact has too many layers and cosign should abort processing it. | ||
type MaxLayersExceeded struct { | ||
value int64 | ||
maximum int64 | ||
} | ||
|
||
func NewMaxLayersExceeded(value, maximum int64) *MaxLayersExceeded { | ||
return &MaxLayersExceeded{value, maximum} | ||
} | ||
|
||
func (e *MaxLayersExceeded) Error() string { | ||
return fmt.Sprintf("number of layers (%d) exceeded the limit (%d)", e.value, e.maximum) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.