The contributor and community take security bugs in PodSalsa seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions.
To report a security issue, please use the GitHub Security Advisory "Report a Vulnerability" tab.
The contributor will send a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.
The release workflow creates provenance for its builds using the SLSA standard, which conforms to the Level 3 specification. The provenance is stored in the multiple.intoto.jsonl
file of each release and can be used to verify the integrity and authenticity of the release artifacts.
All signatures are created by Cosign using the keyless signing method. An overview how the keyless signing works can be found here.
To verify the release artifacts, you will need the slsa-verifier, cosign and crane binaries. See the prerequisites verification for installation instructions.
All of the following commands require the VERSION
environment variable to be set to the version of the release you want to verify. You can set the variable manually or the the latest version with the following command:
# get the latest release
export VERSION=$(curl -s "https://api.github.com/repos/janfuhrer/podsalsa/releases/latest" | jq -r '.tag_name')
You can manually inspect the provenance of the release artifacts (without containers) by decoding the multiple.intoto.jsonl
file.
# download the provenance file
curl -L -O https://github.com/janfuhrer/podsalsa/releases/download/$VERSION/multiple.intoto.jsonl
# decode the payload
cat multiple.intoto.jsonl | jq -r '.payload' | base64 -d | jq
To verify the release artifacts (go binaries and SBOMs) you can use the slsa-verifier
. This verification works for all release artifacts (*.tar.gz
, *.zip
, *.sbom.json
).
# example for the "podsalsa-darwin-amd64.tar.gz" artifact
export ARTIFACT=podsalsa_${VERSION}_darwin_amd64.tar.gz
# download the artifact
curl -L -O https://github.com/janfuhrer/podsalsa/releases/download/$VERSION/$ARTIFACT
# download the provenance file
curl -L -O https://github.com/janfuhrer/podsalsa/releases/download/$VERSION/multiple.intoto.jsonl
# verify the artifact
slsa-verifier verify-artifact \
--provenance-path multiple.intoto.jsonl \
--source-uri github.com/janfuhrer/podsalsa \
--source-tag $VERSION \
$ARTIFACT
The output should be: PASSED: Verified SLSA provenance
.
Verify with SLSA verifier
The slsa-verifier
can also verify docker images. Verification can be done by tag or by digest. We recommend to always use the digest to prevent TOCTOU attacks, as an image tag is not immutable.
IMAGE=ghcr.io/janfuhrer/podsalsa:$VERSION
# get the image digest and append it to the image name
# e.g. ghcr.io/janfuhrer/podsalsa:v0.2.0@sha256:...
IMAGE="${IMAGE}@"$(crane digest "${IMAGE}")
# verify the image
slsa-verifier verify-image \
--source-uri github.com/janfuhrer/podsalsa \
--provenance-repository ghcr.io/janfuhrer/signatures \
--source-versioned-tag $VERSION \
$IMAGE
The output should be: PASSED: Verified SLSA provenance
.
Verify with Cosign
As an alternative to the SLSA verifier, you can use cosign
to verify the provenance of the container images. Cosign also supports validating the attestation against CUE
policies (see Validate In-Toto Attestation for more information), which is useful to ensure that some specific requirements are met. We provide a policy.cue file to verify the correct workflow has triggered the release and that the image was generated from the correct source repository.
# download policy.cue
curl -L -O https://raw.githubusercontent.com/janfuhrer/podsalsa/main/policy.cue
# verify the image with cosign
COSIGN_REPOSITORY=ghcr.io/janfuhrer/signatures cosign verify-attestation \
--type slsaprovenance \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp '^https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@refs/tags/v[0-9]+.[0-9]+.[0-9]+$' \
--policy policy.cue \
$IMAGE | jq
Example output:
will be validating against CUE policies: [policy.cue]
Verification for ghcr.io/janfuhrer/podsalsa:v0.4.0-rc.7@sha256:b76ecae19894c6fe57bcf81ff285e99d2f732bffcc9930fa77a86101edd59015 --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- Existence of the claims in the transparency log was verified offline
- The code-signing certificate was verified using trusted certificate authority certificates
Certificate subject: https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@refs/tags/v2.0.0
Certificate issuer URL: https://token.actions.githubusercontent.com
GitHub Workflow Trigger: push
GitHub Workflow SHA: b51bec9abab403d55c54d2c9b60a12433cc9e102
GitHub Workflow Name: goreleaser
GitHub Workflow Repository: janfuhrer/podsalsa
GitHub Workflow Ref: refs/tags/v0.4.0-rc.7
{
"payloadType": "application/vnd.in-toto+json",
(...)
The container images are additionally signed with cosign. The signature can be verified with the cosign
binary.
Important: only the multi-arch image is signed, not the individual platform images.
COSIGN_REPOSITORY=ghcr.io/janfuhrer/signatures cosign verify \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp '^https://github.com/janfuhrer/podsalsa/.github/workflows/release.yml@refs/tags/v[0-9]+.[0-9]+.[0-9]+(-rc.[0-9]+)?$' \
$IMAGE | jq
Example output:
Verification for ghcr.io/janfuhrer/podsalsa@sha256:b76ecae19894c6fe57bcf81ff285e99d2f732bffcc9930fa77a86101edd59015 --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- Existence of the claims in the transparency log was verified offline
- The code-signing certificate was verified using trusted certificate authority certificates
[
{
"critical": {
(...)
If you want to see the entire certificate of the signature, you can use the following command:
COSIGN_REPOSITORY=ghcr.io/janfuhrer/signatures cosign verify \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp '^https://github.com/janfuhrer/podsalsa/.github/workflows/release.yml@refs/tags/v[0-9]+.[0-9]+.[0-9]+(-rc.[0-9]+)?$' \
$IMAGE | jq -r '.[].optional.Bundle.Payload.body' | \
base64 -d | jq -r '.spec.signature.publicKey.content' | \
base64 -d | openssl x509 -text -noout
Important
Verifying the provenance of a container image ensures the integrity and authenticity of the image because the provenance (with the image digest) is signed with Cosign. The container images themselves are also signed with Cosign, but the signature is not necessary for verification if the provenance is verified. Provenance verification is a stronger security guarantee than image signing because it verifies the entire build process, not just the final image. Image signing is therefore not essential if provenance verification is.
Since all release artifacts can be verified with the slsa-verifier
, a checksum file is not necessary (the integrity is already verified by the SLSA Verifier). A use case might be to verify the integrity of downloaded files and only rely only on Cosign instead of the SLSA verifier.
The checksum file can be verified with cosign
as follows:
# download the checksum
curl -L -O https://github.com/janfuhrer/podsalsa/releases/download/$VERSION/checksums.txt
# verify the checksum file
cosign verify-blob \
--certificate https://github.com/janfuhrer/podsalsa/releases/download/$VERSION/checksums.txt.pem \
--signature https://github.com/janfuhrer/podsalsa/releases/download/$VERSION/checksums.txt.sig \
--certificate-identity-regexp '^https://github.com/janfuhrer/podsalsa/.github/workflows/release.yml@refs/tags/v[0-9]+.[0-9]+.[0-9]+(-rc.[0-9]+)?$' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
checksums.txt
The output should be: Verified OK
.
The Software Bill of Materials (SBOM) is generated in CycloneDX JSON format for each release and can be used to verify the project's dependencies.
The SBOMs of the Go binary archives are provided in the *.tar.gz.sbom.json
files of the release and can be verified using the slsa-verifier
(see Verify the provenance of release artifacts).
The SBOMs of the container is attestated with Cosign and uploaded to the ghcr.io/janfuhrer/sbom
repository. The SBOMs can be verified with the cosign
binary.
Important: Only the multi-arch image has a SBOM, not the individual platform images.
Verify provenance of the SBOM
# download policy-sbom.cue
curl -L -O https://raw.githubusercontent.com/janfuhrer/podsalsa/main/policy-sbom.cue
COSIGN_REPOSITORY=ghcr.io/janfuhrer/sbom cosign verify-attestation \
--type cyclonedx \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp '^https://github.com/janfuhrer/podsalsa/.github/workflows/release.yml@refs/tags/v[0-9]+.[0-9]+.[0-9]+(-rc.[0-9]+)?$' \
--policy policy-sbom.cue \
$IMAGE | jq -r '.payload' | base64 -d | jq
Example output:
will be validating against CUE policies: [policy-sbom.cue]
Verification for ghcr.io/janfuhrer/podsalsa:v0.4.0-rc.7@sha256:b76ecae19894c6fe57bcf81ff285e99d2f732bffcc9930fa77a86101edd59015 --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- Existence of the claims in the transparency log was verified offline
- The code-signing certificate was verified using trusted certificate authority certificates
Certificate subject: https://github.com/janfuhrer/podsalsa/.github/workflows/release.yml@refs/tags/v0.4.0-rc.7
Certificate issuer URL: https://token.actions.githubusercontent.com
GitHub Workflow Trigger: push
GitHub Workflow SHA: b51bec9abab403d55c54d2c9b60a12433cc9e102
GitHub Workflow Name: goreleaser
GitHub Workflow Repository: janfuhrer/podsalsa
GitHub Workflow Ref: refs/tags/v0.4.0-rc.7
{
"_type": "https://in-toto.io/Statement/v0.1",
(...)
Download SBOM
If you want to download the SBOM of the container image, you can use the following command:
COSIGN_REPOSITORY=ghcr.io/janfuhrer/sbom cosign verify-attestation \
--type cyclonedx \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp '^https://github.com/janfuhrer/podsalsa/.github/workflows/release.yml@refs/tags/v[0-9]+.[0-9]+.[0-9]+(-rc.[0-9]+)?$' \
--policy policy-sbom.cue \
$IMAGE | jq -r '.payload' | base64 -d | jq -r '.predicate' > sbom.json
How to communicate with the Rekor transparency log directly is described in the Rekor documentation.