Skip to content

SLSA Build Provenance

OpenMed release artifacts carry SLSA provenance generated by GitHub Actions artifact attestations. The provenance binds each subject to the source commit, source ref, builder workflow, and the workflow identity that signed the attestation.

Release coverage

  • Python wheel and source distribution files are built and checked by the reusable .github/workflows/provenance.yml job before the PyPI upload job starts. The job also attempts to generate and verify SLSA provenance, and uploads that evidence when GitHub OIDC attestation services are available.
  • The GHCR manifest list is built by .github/workflows/container-multiarch.yml and attested by digest after the image is pushed.
  • When attestation succeeds, the workflows verify the https://slsa.dev/provenance/v1 predicate, source commit, source ref, and signer workflow before uploading provenance evidence.

The PyPI publish action currently uploads with the project-scoped PyPI API token, so PyPI-native Sigstore attestations are disabled. When GitHub OIDC attestation succeeds, the SLSA provenance workflow provides the repository-level attestation and digest manifest that downstream users can verify with the GitHub CLI.

Online verification

Download the artifact you plan to use, then verify it against the OpenMed repository and the expected release tag:

VERSION=v1.8.0
COMMIT=<release-commit-sha>
ARTIFACT=openmed-1.8.0-py3-none-any.whl

sha256sum "$ARTIFACT"
gh attestation verify "$ARTIFACT" \
  --repo maziyarpanahi/openmed \
  --predicate-type https://slsa.dev/provenance/v1 \
  --signer-workflow github.com/maziyarpanahi/openmed/.github/workflows/provenance.yml \
  --source-digest "$COMMIT" \
  --source-ref "refs/tags/$VERSION"

Use the same command for the source distribution by setting ARTIFACT to the downloaded openmed-1.8.0.tar.gz file.

For the container image, verify the manifest-list digest rather than a mutable tag:

VERSION=v1.8.0
COMMIT=<release-commit-sha>
IMAGE=ghcr.io/maziyarpanahi/openmed:$VERSION
DIGEST="$(docker buildx imagetools inspect "$IMAGE" --format '{{ .Manifest.Digest }}')"

gh attestation verify "oci://ghcr.io/maziyarpanahi/openmed@$DIGEST" \
  --repo maziyarpanahi/openmed \
  --predicate-type https://slsa.dev/provenance/v1 \
  --signer-workflow github.com/maziyarpanahi/openmed/.github/workflows/container-multiarch.yml \
  --source-digest "$COMMIT" \
  --source-ref "refs/tags/$VERSION"

Offline verification

Offline verification needs the artifact, the attestation bundle, and the trusted root material. Fetch the bundle and roots while online:

ARTIFACT=openmed-1.8.0-py3-none-any.whl

gh attestation download "$ARTIFACT" \
  --repo maziyarpanahi/openmed \
  --predicate-type https://slsa.dev/provenance/v1
gh attestation trusted-root > trusted_root.jsonl
sha256sum "$ARTIFACT" > artifact.sha256

Move the artifact, artifact.sha256, trusted_root.jsonl, and the downloaded sha256:*.jsonl bundle into the offline environment. Verify the local digest first, then verify the bundle:

VERSION=v1.8.0
COMMIT=<release-commit-sha>
ARTIFACT=openmed-1.8.0-py3-none-any.whl
BUNDLE=<downloaded-sha256-bundle>.jsonl

sha256sum --check artifact.sha256
gh attestation verify "$ARTIFACT" \
  --repo maziyarpanahi/openmed \
  --bundle "$BUNDLE" \
  --custom-trusted-root trusted_root.jsonl \
  --predicate-type https://slsa.dev/provenance/v1 \
  --signer-workflow github.com/maziyarpanahi/openmed/.github/workflows/provenance.yml \
  --source-digest "$COMMIT" \
  --source-ref "refs/tags/$VERSION"

For the container image, download the attestation bundle while online:

VERSION=v1.8.0
IMAGE=ghcr.io/maziyarpanahi/openmed:$VERSION
DIGEST="$(docker buildx imagetools inspect "$IMAGE" --format '{{ .Manifest.Digest }}')"

gh attestation download "oci://ghcr.io/maziyarpanahi/openmed@$DIGEST" \
  --repo maziyarpanahi/openmed \
  --predicate-type https://slsa.dev/provenance/v1
gh attestation trusted-root > trusted_root.jsonl
printf '%s  %s\n' "$DIGEST" "ghcr.io/maziyarpanahi/openmed@$DIGEST" \
  > image-digest.txt

In the offline environment, verify the downloaded OCI bundle against the pinned digest:

VERSION=v1.8.0
COMMIT=<release-commit-sha>
DIGEST=sha256:<manifest-list-digest>
BUNDLE=<downloaded-sha256-bundle>.jsonl

gh attestation verify "oci://ghcr.io/maziyarpanahi/openmed@$DIGEST" \
  --repo maziyarpanahi/openmed \
  --bundle "$BUNDLE" \
  --custom-trusted-root trusted_root.jsonl \
  --predicate-type https://slsa.dev/provenance/v1 \
  --signer-workflow github.com/maziyarpanahi/openmed/.github/workflows/container-multiarch.yml \
  --source-digest "$COMMIT" \
  --source-ref "refs/tags/$VERSION"