* Add cosign-specific user-agent to all HTTP requests
This change addresses issue #4692 by ensuring that all HTTP requests
made by cosign identify with a proper user-agent that includes both
the cosign version and sigstore-go version.
Signed-off-by: Carlos Panato <ctadeu@gmail.com>
* Scope sigstore-go user-agent to sigstore-go code paths
Keep the global user-agent as cosign/<version> (os; arch) and only
send cosign/<version> sigstore-go/<version> (os; arch) on requests
made through sigstore-go. Fulcio and TSA clients built in SignData
now use a transport that overrides sigstore-go's default user-agent.
Rekor requests made via sigstore-go still use sigstore-go's
user-agent until sigstore-go exposes a way to set it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Carlos Panato <ctadeu@gmail.com>
* Set cosign user-agent on sigstore-go Fulcio, TSA and Rekor clients
Bump sigstore-go to main to pick up sigstore/sigstore-go#686, which
adds a UserAgent option and always appends sigstore-go/<version>.
Pass cosign's user-agent through it and drop the transport wrapper
and the sigstore-go version lookup.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Carlos Panato <ctadeu@gmail.com>
---------
Signed-off-by: Carlos Panato <ctadeu@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Fixes#5018
Motivation
Signing with a HashiCorp Vault Transit KMS ECDSA P-521 key fails with
"signing digest: signing bundle: error signing bundle: unexpected
length of digest for hash function specified". This is a regression
in the bundle-signing path introduced when SignerVerifierKeypair was
added: it correctly computes the digest using the key's own default
hash algorithm (SHA-512 for P-521), but never told the underlying
signer.SignMessage which hash algorithm that digest was produced with.
KMS-backed SignerVerifiers created via
pkg/signature/keys.go:SignerVerifierFromKeyRef are constructed with a
hardcoded crypto.SHA256 default (unrelated to the actual key's curve),
so sigstore-go's ComputeDigestForSigning fell back to that default,
saw a 64-byte digest against an expected 32-byte SHA-256 digest, and
rejected it with the mismatch error above.
Approach
internal/key/svkeypair.go: SignerVerifierKeypair.SignData now also
passes signatureoptions.WithCryptoSignerOpts(hashType) alongside
WithDigest(digest), so the signer is told exactly which hash algorithm
produced the digest, regardless of what hash it was constructed with
by default. This affects every SignerVerifier-backed signing path (any
KMS provider, not just Vault) whenever the key's natural hash isn't
SHA-256 (e.g. P-384/P-521 ECDSA, larger RSA keys). For keys whose
natural hash is already SHA-256 (e.g. default P-256), this is a no-op:
the newly-passed option matches the signer's existing default.
Validation
go build ./...
go test ./internal/key/... ./pkg/signature/... ./pkg/cosign/bundle/... -count=1
ok github.com/sigstore/cosign/v3/internal/key
ok github.com/sigstore/cosign/v3/pkg/signature
ok github.com/sigstore/cosign/v3/pkg/cosign/bundle
Added TestKMSKeypair_ECDSA_P521_SignData, which reproduces the digest
length/hash mismatch reported in the issue (verified it fails without
this fix with "expected underlying signer to be given crypto.SHA512
opts matching the digest, got <nil>", and passes with it). This was
verified with a unit test against a mock SignerVerifier reproducing
the KMS signer's option-handling behavior; it was not validated
against a live HashiCorp Vault instance.
Signed-off-by: Pujitha Paladugu <10557236+pujitha24@users.noreply.github.com>
Bundle() decompressed the new-bundle-format attestation layer and read all of
it into memory with no size check, while every other layer read in pkg/oci
calls payloadsize.CheckSize first. A registry the user does not control could
make cosign verify-attestation --new-bundle-format allocate without bound from
a small compressed layer.
The size a registry declares is the compressed size, and this is the only one
of these reads that goes through Uncompressed(), so checking that size is
necessary but not sufficient. This does both: the declared size is checked
first so an oversized layer is rejected before anything is read, and the
decompressed stream is then bounded by the same limit.
GetBundles calls Bundle() for every manifest in a referrers index and swallows
the error with continue, since non-Sigstore referrers are expected there, so
without the second check each oversized layer in an index was read in full
before its error was reached.
MaxSize is exported from the payload size package because a caller reading a
decompressed stream needs the limit itself rather than a yes or no answer
about a size it already knows.
Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
* chore(deps): bump the all group across 1 directory with 2 updates
Bumps the all group with 2 updates in the / directory: golang and golangci/golangci-lint.
Updates `golang` from 1.26.5 to 1.27.0
Updates `golangci/golangci-lint` from v2.12.2 to v2.13.1
---
updated-dependencies:
- dependency-name: golang
dependency-version: 1.27.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: all
- dependency-name: golangci/golangci-lint
dependency-version: v2.13.1
dependency-type: direct:production
dependency-group: all
...
Signed-off-by: dependabot[bot] <support@github.com>
* address lints
Signed-off-by: Bob Callaway <bcallaway@google.com>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Bob Callaway <bcallaway@google.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Bob Callaway <bcallaway@google.com>
This change refactors the signing path in all signing and attestation commands such that all signing events occur via sigstore-go, not just those in which a signing config is used.
Signed-off-by: Aaron Lew <64337293+aaronlew02@users.noreply.github.com>
Recording signatures to Rekor v2 can take up to 10 seconds. We want to
avoid someone killing the process while waiting for a response from
Rekor, otherwise the user will have to re-sign the artifact.
Signed-off-by: Hayden <8418760+haydentherapper@users.noreply.github.com>
* Bump sigstore-go, support alternative hash algorithms with keys
sigstore-go now handles non-ECDSA-P-256 signatures with Rekor v2. To
support verification, we also need a way to provide alternative hash
algorithms to the default SHA-256. cosign verify already had a flag for
this, so I added the flag to all verify commands. In the future, when we
are only processing bundles, we can lookup the default hash algorithm
given the key.
Signed-off-by: Hayden <8418760+haydentherapper@users.noreply.github.com>
* lint fmt
Signed-off-by: Hayden <8418760+haydentherapper@users.noreply.github.com>
* Drop support for Fulcio with ed25519ph key
We've chosen to not support this in sigstore-go, so we'll also remove
this from Cosign. This is a niche edge case where a user provides an
ed25519 key or algorithm and requests a cert and logs it to Rekor. We'll
revisit this if there's demand or when we support the prehash variant in
Fulcio.
Signed-off-by: Hayden <8418760+haydentherapper@users.noreply.github.com>
---------
Signed-off-by: Hayden <8418760+haydentherapper@users.noreply.github.com>
Co-authored-by: Hayden <8418760+haydentherapper@users.noreply.github.com>
* Support self-managed keys when signing with sigstore-go
This creates a wrapper around the Keypair interface when a
SignerVerifier is provided for signing with KMS or any other provided
keys. This also retains support for --issue-certificate to request a
certificate for a managed key.
Fixes#4327
Signed-off-by: Hayden <8418760+haydentherapper@users.noreply.github.com>
* Add issue-certificate flags to attest and attest-blob
This is for uniformity with sign/sign-blob.
Signed-off-by: Hayden <8418760+haydentherapper@users.noreply.github.com>
* Refactor SignerFromKeyOpts to split Fulcio signer into its own method
Now, we can generate a SignerVerifier from a provided key without
mandating that we also request a Fulcio certificate when
"issue-certificate" is provided.
Signed-off-by: Hayden <8418760+haydentherapper@users.noreply.github.com>
* Use default options to load key material
Signed-off-by: Hayden <8418760+haydentherapper@users.noreply.github.com>
---------
Signed-off-by: Hayden <8418760+haydentherapper@users.noreply.github.com>
Use sigstore/sigstore signature.LoadSignerVerifierFromPrivateKey to load default verifiers given a private key.
Signed-off-by: Riccardo Schirone <riccardo.schirone@trailofbits.com>
When developing locally, with the e2e build tag set, there's an import
cycle. test/helpers.go imports "cmd/cosign/cli/verify", which imports
"test" in test files in the verify package. This change breaks the
import cycle by moving certificate utilities to an internal test
directory.
Signed-off-by: Hayden <8418760+haydentherapper@users.noreply.github.com>
* Remove explicit staticcheck and unused linter enables
They are enabled by default. For consistency, do not list them like
others that are enabled by default (for example govet) are not
explicitly listed either.
Signed-off-by: Ville Skyttä <ville.skytta@iki.fi>
* Enable makezero and nilnesserr linters
There are no findings from either at the moment, but they serve useful
purposes.
Signed-off-by: Ville Skyttä <ville.skytta@iki.fi>
* Ensure closing of TSA response body, enable bodyclose linter
This was flagged by bodyclose.
Signed-off-by: Ville Skyttä <ville.skytta@iki.fi>
* Vet internal ui.Infof/Warnf uses
Signed-off-by: Ville Skyttä <ville.skytta@iki.fi>
* Enable usestdlibvars linter, address findings
Signed-off-by: Ville Skyttä <ville.skytta@iki.fi>
* test: update e2e rekor service count
https://github.com/sigstore/cosign/pull/4213#pullrequestreview-2876276830
Signed-off-by: Ville Skyttä <ville.skytta@iki.fi>
* Update e2e_test.sh to handle different healthy service totals
Rekor has healthchecks for 5 services, Fulcio currently has healthchecks for 3.
Signed-off-by: Hayden B <haydentherapper@users.noreply.github.com>
---------
Signed-off-by: Ville Skyttä <ville.skytta@iki.fi>
Signed-off-by: Hayden B <haydentherapper@users.noreply.github.com>
Co-authored-by: Hayden B <haydentherapper@users.noreply.github.com>
* 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 <colleenmurphy@google.com>
* 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 <colleenmurphy@google.com>
---------
Signed-off-by: Colleen Murphy <colleenmurphy@google.com>
* Set rekor URL for online and offline tests
Some tests were setting the REKOR_URL environment variable to try to
test offline verification. This variable is no longer read so it was not
doing anything. This change removes the variable and instead sets
RekorURL in the command to either the local rekor instance (so that the
public instance is not used) or to a bad url with Offline set to true so
that offline verification is truly tested.
This change also removes the COSIGN_EXPERIMENTAL variable which is no
longer used, and replaces os.Setenv with testing.Setenv which
localizes the environment setting to the scope of the test and removes
the need for a cleanup function.
Signed-off-by: Colleen Murphy <colleenmurphy@google.com>
* Fix cleanup in E2E script
Calling trap multiple times replaces the last signal handler rather than
appending to it. This change ensures that the most recent trap includes
all previous traps so that all cleanups are executed.
Signed-off-by: Colleen Murphy <colleenmurphy@google.com>
* Move verify tests from shell script to Go suite
Move the `cosign dockerfile verify` and `cosign manifest verify` tests
out of the shell script and into the e2e Go test suite file with all the
other tests. This makes them consistent to manage.
The initialization of fulcio roots in other tests pollutes the trust
root in the new tests, so a reset is added to the fulcioroots package
for testing only.
Signed-off-by: Colleen Murphy <colleenmurphy@google.com>
* Use local services for verify tests
Update TestDockerfileVerify and TestManifestVerify to sign ephemeral
images within the tests so that the signatures can be created with and
verified from the locally running Fulcio and Rekor instances instead of
verifying images with the public Rekor instance, so that the tests no
longer depend on external services.
The images are signed using --identity-token to avoid changing the
nature of the verification tests, which were originally written to be
keyless. A mock OIDC server is provisioned to provide the token and
enable verification.
Signed-off-by: Colleen Murphy <colleenmurphy@google.com>
* Set rekor env variable in Go test suite
Move the setting of SIGSTORE_REKOR_PUBLIC_KEY from the e2e shell script
to the Go test suite, so that only the tests that need it have it set
and the shell script is doing less setup. Also remove unnecessary
instances of os.RemoveAll for temporary directories that the Go testing
framework will automatically clean up.
Signed-off-by: Colleen Murphy <colleenmurphy@google.com>
---------
Signed-off-by: Colleen Murphy <colleenmurphy@google.com>
* add 'cosign sign' command-line parameters for mTLS
Add command-line parameters for key/cert/cacert used for
the connection to the TSA server.
Fixes#3006
Signed-off-by: Dmitry S <dsavints@gmail.com>
* simplify ServerName validation
Signed-off-by: Dmitry S <dsavints@gmail.com>
* add 'tsa-mtls.sh to test mTLS to TSA
Signed-off-by: Dmitry S <dsavints@gmail.com>
* add tsa mtls test to github actions
Signed-off-by: Dmitry S <dsavints@gmail.com>
* use smallstep's step to generate test certificates
Signed-off-by: Dmitry S <dsavints@gmail.com>
* in e2e_tsa_mtls.sh, build timestamp-server only if not found
Signed-off-by: Dmitry S <dsavints@gmail.com>
* add test/gencert utility, copyright
Signed-off-by: Dmitry S <dsavints@gmail.com>
---------
Signed-off-by: Dmitry S <dsavints@gmail.com>
Using time.Now() makes this unreproducible and causes a lot of churn
when re-running the same command.
Signed-off-by: Jon Johnson <jon.johnson@chainguard.dev>
* Support non-Sigstore TSA requests
This changes the client to instead simply exchange a TSQ for a TSR given
a URL to the API. This will mean that for clients using timestamping
currently, they will need to update their Cosign calls to use the full
path (e.g. tsa.sigstore/api/v1/timestamp)
Fixes https://github.com/sigstore/cosign/issues/2704
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
* Address comments
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
---------
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
* Add COSIGN_OCI_EXPERIMENTAL, push .sig/.sbom using OCI 1.1+ digest tag
Signed-off-by: Josh Dolitsky <josh@dolit.ski>
* upgrade to latest ggcr with referrers API support
Signed-off-by: Josh Dolitsky <josh@dolit.ski>
* unexport methods whereever possible
Signed-off-by: Josh Dolitsky <josh@dolit.ski>
* Use ui logger wherever possible
Signed-off-by: Josh Dolitsky <josh@dolit.ski>
* add TODO about using created annotations
Signed-off-by: Josh Dolitsky <josh@dolit.ski>
* remove logging about unable to to find new type of attachment
Signed-off-by: Josh Dolitsky <josh@dolit.ski>
* fixes from review
Signed-off-by: Josh Dolitsky <josh@dolit.ski>
* push the config blob
Signed-off-by: Josh Dolitsky <josh@dolit.ski>
* run docgen
Signed-off-by: Josh Dolitsky <josh@dolit.ski>
* fix for e2e tests
Signed-off-by: Josh Dolitsky <josh@dolit.ski>
---------
Signed-off-by: Josh Dolitsky <josh@dolit.ski>
This library:
- Is testable.
- Is consistent across the CLI.
Related to (does not fix) #2296 and #2204.
Signed-off-by: Zachary Newman <zjn@chainguard.dev>
Signed-off-by: Zachary Newman <zjn@chainguard.dev>
* Update timestamp dependency to use updated verifier
Verification now properly verifies the full certificate chain in
addition to supporting other verification, like nonce (useful for
verifying on signing).
Also updated the flag name to use "certificate" rather than "cert" to be
in line with other flag names.
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
* Allow no TSA certificates
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
* fix v2
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
* Update doc comments
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
* Fix timestamp verification, add verify-blob tests
While adding unit tests for verify-blob with timestamping, I found that
we try to verify with the current time if no bundle is provided, even if
we have a timestamp. I cleaned up this function to check the timestamp
time and bundle time if either are provided, and if neither is provided,
check against the current time.
I also added a mock client to clean up tests. I'll move this mock client
over to the timestamp-authority repo.
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
* Remove println
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
* Updates to Timestamp signing and verification
* Switch to using the raw signature rather than base64 signature for OCI
and blob signing
* For blob signing, write only the timestamp to disk, not the
LocalSignedPayload (since that's already written with the bundle)
* For blob verification, expect only a timestamp in the file. If you
don't pass a bundle, you'll need to also pass the signature by flag
* Some nits from the previous PR
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
* Add testing in verify, update e2e test
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
* Fix test
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
* Add missing setting of SkipTlogVerify
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
* Address comments
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
* Fix docs
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
* Address nits
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
* Fix e2e test
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
sign-blob always loads the entire blob into memory. This can lead to
problems when signing large blob files and increased memory usage.
Signed-off-by: Anish Shah <anishshah@google.com>
Signed-off-by: Anish Shah <anishshah@google.com>
This fixes a regression where intermediates, when not present in the
intermediate certificate pool, would be fetched from the OCI chain
annotation.
Ref #1554, which includes more details
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>