Advanced Guides

Verifying images

Every image we publish is signed and carries a software bill of materials (SBOM) and build provenance. Use them to confirm that the image you pulled came from our GitHub Actions workflows and to see exactly what went into it.

Why verify an image

A tag is only a pointer. Whoever controls it can point 8.5-cli at a different image. A signature check proves the image was published by the serversideup/docker-php repository's own publish workflow, from main or a release tag. The SBOM and provenance tell you what is in the image and how it was built, which is what most supply-chain policies and audits ask for.

Images published before we started signing have provenance but no SBOM or signature. Version-pinned tags such as 8.4-fpm-nginx-v4.3.5 are never rebuilt. Older ones will always fail the signature check. Floating tags like 8.5-cli are signed from their next rebuild on.

Verify the signature

Install cosign by following the Sigstore installation guide, then run:

Terminal
cosign verify serversideup/php:8.5-cli \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --certificate-identity-regexp '^https://github\.com/serversideup/docker-php/\.github/workflows/service_publish-images\.yml@refs/(heads/main|tags/v.+)$'

The two flags say who you trust. The issuer is GitHub Actions. The identity is our publish workflow running from main or a v release tag. cosign exits with an error if the image has no signature from that identity.

Signing is keyless: there is no public key to download. Each signature is tied to the workflow run that made it through GitHub's OIDC token and recorded in Sigstore's public transparency log.

Docker Hub and GitHub Packages each hold their own signature. The same command works for ghcr.io/serversideup/php:8.5-cli. The signature covers the image index, which references the image for every platform along with its SBOM and provenance. One check covers all of them.

Read the SBOM

The SBOM is an SPDX document that lists the packages in the image. Read it for one platform with Docker Buildx:

Terminal
docker buildx imagetools inspect serversideup/php:8.5-cli \
  --format '{{ json (index .SBOM "linux/amd64").SPDX }}'

Use linux/arm64 for the arm64 image. On an image published before SBOMs were added, the command prints null.

Read the build provenance

The provenance is a SLSA record of how the image was built: the source commit, the Dockerfile, the build arguments, and the base images. We publish it in full (mode=max):

Terminal
docker buildx imagetools inspect serversideup/php:8.5-cli \
  --format '{{ json (index .Provenance "linux/amd64").SLSA }}'

To see only the commit and Dockerfile an image was built from, read invocation.configSource:

Terminal
docker buildx imagetools inspect serversideup/php:8.5-cli \
  --format '{{ json (index .Provenance "linux/amd64").SLSA.invocation.configSource }}'
Output
{
  "digest": {
    "sha1": "af1462e3abf8c67ff3fb78141255adc33de5bf2c"
  },
  "entryPoint": "src/variations/cli/Dockerfile",
  "uri": "https://github.com/serversideup/docker-php.git#af1462e3abf8c67ff3fb78141255adc33de5bf2c"
}

Scan it yourself

You don't have to trust our scan. The images are public and work with any scanner. For example, with Grype:

Terminal
grype serversideup/php:8.5-cli

Add --only-fixed to list only the findings that have a fix available. Those are the ones a rebuild or an upgrade can change. See fixable and unfixed findings for why the full list is usually much longer.