Supply-Chain Security¶
Opencomplai ships official container images with cryptographic signatures and software bill of materials (SBOM) attestations. This page covers how the signatures are produced and how you can verify them before deploying.
Check which images exist
Release images are built, signed and attested by supply-chain.yml in the release repository Opencomplai/opencomplai-enterprise when a vX.Y.Z tag passes the Trivy release gate, and pushed to ghcr.io/opencomplai/opencomplai-enterprise/<service>. You can pull and verify them only if the GHCR packages are public. Package visibility and the published tags are unverified at the time of writing: check the registry for the tags that actually exist and use one as <version> below.
How official images are signed¶
Every official image under ghcr.io/opencomplai/opencomplai-enterprise/<service> (the workflow lowercases the release repository name Opencomplai/opencomplai-enterprise to form the path) is built, signed, and attested by the supply-chain.yml GitHub Actions workflow in that release repository, whose runs are not public. The workflow runs on every version tag (v*.*.*) and on manual dispatch.
The signing uses cosign keyless mode, backed by the Sigstore public-good infrastructure (Rekor transparency log and Fulcio CA). No long-lived signing key is stored in CI. The signing identity is the workflow's OIDC token, scoped to the Opencomplai/opencomplai-enterprise repository and the supply-chain.yml workflow file.
The SBOM is generated by syft in SPDX-JSON format and attached to the image as a cosign in-toto attestation (--type spdxjson).
Verifying an image signature¶
The command exits 0 and prints the signing certificate when the signature is valid and the identity matches the expected workflow.
Verifying the SBOM attestation¶
Use the helper script bundled with the repository:
It runs both cosign verify and cosign verify-attestation and decodes the predicate name from the SBOM payload. A full image reference (anything with a /) is used as is; set OPENCOMPLAI_RELEASE_REPO=<owner>/<repo> to check an image built by supply-chain.yml in another repository.
SBOM format¶
The SBOM is SPDX-JSON (SPDX 2.3). You can extract it from the attestation and pipe it into other tooling:
Scanning for known vulnerabilities¶
syft and grype compose cleanly:
CI runs an equivalent scan on every pull request via the vulnerability-scan job of the ci-docker.yml workflow in the release repository. CRITICAL and HIGH fixable findings fail the build.
That job scans all five service images — gateway-api, risk-engine, evidence-vault, doc-generator and egress-proxy. It previously covered only gateway-api, so the other four were signed and SBOM'd at release but never CVE-scanned: an SBOM records what is in an image, it does not say the contents are safe.
The same scan now also runs as a release gate in supply-chain.yml in the release repository, before the image is pushed or signed. Signing first would mean attesting an image nobody had checked.
Unfixable findings are excluded (ignore-unfixed). They cannot be acted on here, and a gate that cannot be made green is one people learn to route around.
The Trivy record, infra/docker/TRIVY-LAST-RUN.md, is a point-in-time record of the release gate's scan on the five images. It is not a guarantee that the images are clean today. Refresh it by re-running the build and scan commands recorded in the file whenever the pinned Trivy version or a FROM base digest changes; test_docker_images_hardening.py fails until it matches.
Python packages¶
PyPI releases are published with Trusted Publishing (OIDC), with no API token and no long-lived secret. Every distribution carries PEP 740 attestations, generated at upload and shown on the file's PyPI page.
SLSA build provenance is not attested: GitHub's artifact attestations are not available for the private release repository on the current billing plan.
The release workflow, publish-pypi.yml, checks the tag against the package versions, runs the wheel smoke test and generates a CycloneDX SBOM per package before anything is uploaded. Those SBOMs are build artifacts of the workflow run; they are not uploaded to PyPI or to the GitHub Release.