--- id: verifying-signed-artifacts title: Verifying Signed Artifacts sidebar_label: Verify Signed Artifacts description: Learn how to verify Seerr's signed artifacts and SBOM attestations. --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Verifying Signed Artifacts These artifacts are cryptographically signed using [Sigstore Cosign](https://docs.sigstore.dev/quickstart/quickstart-cosign/): - Container images This ensures that the images you pull are authentic, tamper-proof, and built by the official Seerr release pipeline. Additionally each container image also includes a CycloneDX SBOM (Software Bill of Materials) attestation, generated with [Trivy](https://aquasecurity.github.io/trivy/), providing transparency about all dependencies included in the image. --- ## Prerequisites You will need the following tools installed: - [Cosign](https://docs.sigstore.dev/cosign/system_config/installation/) To verify images: - [Docker](https://docs.docker.com/get-docker/) **or** - [Podman](https://podman.io/getting-started/installation) (including [Skopeo](https://github.com/containers/skopeo/blob/main/install.md)) --- # Verifying Signed Images All Seerr container images published to GitHub Container Registry (GHCR) are cryptographically signed using [Sigstore Cosign](https://docs.sigstore.dev/quickstart/quickstart-cosign/). This ensures that the images you pull are authentic, tamper-proof, and built by the official Seerr release pipeline. Each image also includes a CycloneDX SBOM (Software Bill of Materials) attestation, generated with [Trivy](https://aquasecurity.github.io/trivy/), providing transparency about all dependencies included in the image. --- ### Image Locations Official Seerr images are available from: - GitHub Container Registry (GHCR): `ghcr.io/seerr-team/seerr:` - Docker Hub: `seerr/seerr:` You can view all available tags on the [Seerr Releases page](https://github.com/seerr-team/seerr/releases). --- ### Verifying a Specific Release Tag Each tagged release (for example `v2.7.4`) is immutable and cryptographically signed. Verification should always be performed using the image digest (SHA256). #### Retrieve the Image Digest ```bash docker buildx imagetools inspect ghcr.io/seerr-team/seerr:v2.7.4 --format '{{json .Manifest.Digest}}' | tr -d '"' ``` ```bash skopeo inspect docker://ghcr.io/seerr-team/seerr:v2.7.4 --format '{{.Digest}}' ``` Example output: ``` sha256:abcd1234... ``` --- #### Verify the Image Signature ```bash cosign verify ghcr.io/seerr-team/seerr@sha256:abcd1234... \ --certificate-identity "https://github.com/seerr-team/seerr/.github/workflows/release.yml@refs/tags/v2.7.4" \ --certificate-oidc-issuer "https://token.actions.githubusercontent.com" ``` ```bash cosign verify seerr/seerr@sha256:abcd1234... \ --certificate-identity "https://github.com/seerr-team/seerr/.github/workflows/release.yml@refs/tags/v2.7.4" \ --certificate-oidc-issuer "https://token.actions.githubusercontent.com" ``` :::info Successful Verification Example Verification for `ghcr.io/seerr-team/seerr@sha256:abcd1234...` The following checks were performed: - Cosign claims validated - Signatures verified against the transparency log - Certificate issued by Fulcio to the expected workflow identity ::: --- ### Verifying the `latest` Tag :::warning Latest Tag Warning The `latest` tag is **mutable**, meaning it will change with each new release. Always verify the digest that `latest` currently points to. ::: #### Retrieve the Digest for `latest` ```bash docker buildx imagetools inspect ghcr.io/seerr-team/seerr:latest --format '{{json .Manifest.Digest}}' | tr -d '"' ``` ```bash skopeo inspect docker://ghcr.io/seerr-team/seerr:latest --format '{{.Digest}}' ``` Example output: ``` sha256:abcd1234... ``` #### Verify the Signature ```bash cosign verify ghcr.io/seerr-team/seerr@sha256:abcd1234... \ --certificate-identity-regexp "https://github.com/seerr-team/seerr/.github/workflows/release.yml@refs/tags/v.*" \ --certificate-oidc-issuer "https://token.actions.githubusercontent.com" ``` ```bash cosign verify seerr/seerr@sha256:abcd1234... \ --certificate-identity-regexp "https://github.com/seerr-team/seerr/.github/workflows/release.yml@refs/tags/v.*" \ --certificate-oidc-issuer "https://token.actions.githubusercontent.com" ``` :::tip The wildcard `v.*` ensures verification works for any versioned release that `latest` represents. ::: --- ### Verifying SBOM Attestations Each image includes a CycloneDX SBOM attestation. #### Verify the Attestation ```bash cosign verify-attestation ghcr.io/seerr-team/seerr@sha256:abcd1234... \ --type cyclonedx \ --certificate-identity "https://github.com/seerr-team/seerr/.github/workflows/release.yml@refs/tags/v2.7.4" \ --certificate-oidc-issuer "https://token.actions.githubusercontent.com" ``` :::info Successful Verification Example Verification for `ghcr.io/seerr-team/seerr@sha256:abcd1234...` The following checks were performed: - Cosign claims validated - Signatures verified against the transparency log - Certificate issued by Fulcio to the expected workflow identity ::: #### Extract the SBOM for Inspection ```bash cosign verify-attestation ghcr.io/seerr-team/seerr@sha256:abcd1234... \ --type cyclonedx \ --certificate-identity "https://github.com/seerr-team/seerr/.github/workflows/release.yml@refs/tags/v2.7.4" \ --certificate-oidc-issuer "https://token.actions.githubusercontent.com" | jq -r '.payload | @base64d' > sbom.json ``` You can open `sbom.json` in a CycloneDX viewer or analyse it with [Trivy](https://aquasecurity.github.io/trivy/) or [Dependency-Track](https://dependencytrack.org/). --- ### Expected Certificate Identity The expected certificate identity for all signed Seerr images is: ``` https://github.com/seerr-team/seerr/.github/workflows/release.yml@refs/tags/v* ``` This confirms that the image was: - Built by the official Seerr Release workflow - Produced from the seerr-team/seerr repository - Signed using GitHub’s OIDC identity via Sigstore Fulcio --- ### Troubleshooting | Issue | Likely Cause | Suggested Fix | |-------|---------------|----------------| | `no matching signatures` | Incorrect digest or tag | Retrieve the digest again using Docker or Skopeo | | `certificate identity does not match expected` | Workflow reference changed | Ensure your `--certificate-identity` matches this documentation | | `cosign: command not found` | Cosign not installed | Install Cosign from the official release | | `certificate expired` | Old release | Verify a newer tag or digest | --- ### Example: Full Verification Flow ```bash DIGEST=$(docker buildx imagetools inspect ghcr.io/seerr-team/seerr:latest --format '{{json .Manifest.Digest}}' | tr -d '"') cosign verify ghcr.io/seerr-team/seerr@"$DIGEST" \ --certificate-identity-regexp "https://github.com/seerr-team/seerr/.github/workflows/release.yml@refs/tags/v.*" \ --certificate-oidc-issuer "https://token.actions.githubusercontent.com" cosign verify-attestation ghcr.io/seerr-team/seerr@"$DIGEST" \ --type cyclonedx \ --certificate-identity-regexp "https://github.com/seerr-team/seerr/.github/workflows/release.yml@refs/tags/v.*" \ --certificate-oidc-issuer "https://token.actions.githubusercontent.com" ``` ```bash DIGEST=$(skopeo inspect docker://ghcr.io/seerr-team/seerr:latest --format '{{.Digest}}') cosign verify ghcr.io/seerr-team/seerr@"$DIGEST" \ --certificate-identity-regexp "https://github.com/seerr-team/seerr/.github/workflows/release.yml@refs/tags/v.*" \ --certificate-oidc-issuer "https://token.actions.githubusercontent.com" ``` --- ## Further Reading - [Sigstore Documentation](https://docs.sigstore.dev) - [Cosign Verification Guide](https://docs.sigstore.dev/cosign/verifying/verify/) - [CycloneDX Specification](https://cyclonedx.org/specification/overview/) - [Trivy Documentation](https://trivy.dev/latest/docs/) - [Skopeo Documentation](https://github.com/containers/skopeo) - [Podman Documentation](https://podman.io/get-started/) - [Docker Documentation](https://docs.docker.com/) - [Seerr GitHub Repository](https://github.com/seerr-team/seerr)