In March 2024, a maintainer noticed a 500-millisecond SSH login delay and pulled a thread that unraveled CVE-2024-3094 — a backdoor planted inside XZ Utils, a compression library baked into nearly every Linux distribution. The attacker had spent two years building trust as a co-maintainer before slipping malicious code into release tarballs that didn't match the public git history. No vulnerability scanner would have caught it, because the code wasn't "vulnerable" — it was intentionally malicious, and it was signed with legitimate-looking commits. That single near-miss reframed a debate that had simmered since the 2020 SolarWinds Orion compromise: scanning a container image for known CVEs tells you what's inside it, but it says nothing about whether the image is the one your build pipeline actually produced. Container image signing closes that gap. This post walks through what signing verifies, where scanners like Trivy fit, and where they stop.
What does container image signing actually verify?
Container image signing cryptographically proves that a specific image digest was produced by a specific identity and hasn't been altered since — it does not tell you whether the image is free of vulnerabilities. When you sign an image, you're attaching a signature over its SHA-256 content digest, not its tag. Tags like myapp:latest are mutable pointers that can be repointed to a different image tomorrow; digests are immutable. A verifier checks that the digest being pulled matches the digest that was signed, and that the signature traces back to a trusted key or identity (a CI workflow, a specific GitHub Actions OIDC token, or a corporate PKI). This is the mechanism that stops "tag drift" attacks, where an attacker with registry write access swaps the bytes behind a tag without anyone noticing — something that happened in the 2021 Codecov bash uploader compromise, where a modified script sat undetected in CI pipelines for roughly two months before discovery.
Why did keyless signing with Sigstore change adoption?
Sigstore's cosign, released as a Linux Foundation project in 2021, removed the biggest blocker to signing adoption: private key management. Before Sigstore, teams had to generate, rotate, escrow, and protect long-lived signing keys — a burden significant enough that most organizations simply skipped signing outside of regulated environments like financial services or defense. Cosign's keyless flow instead issues a short-lived certificate (valid for about 10 minutes) tied to an OIDC identity — your GitHub Actions workflow, your GitLab pipeline, your Google identity — and records the signing event in a public, append-only transparency log called Rekor. By 2023, Sigstore's public-good instance had logged well over 20 million signing events, and cosign v2.0 (January 2023) made keyless the default recommended path rather than an experimental one. The practical effect: signing went from a PKI project measured in quarters to a CI pipeline step measured in minutes, which is why it's now showing up in default configurations for Kubernetes distributions, npm's provenance attestations, and PyPI's Trusted Publishing rollout.
Can Trivy sign and verify container images?
Trivy, Aqua Security's open-source scanner, is built primarily to detect known CVEs, misconfigurations, exposed secrets, and license issues inside an image — signing and verification are handled by pairing it with separate tooling rather than being native to its core scan engine. Trivy can generate an SBOM and, in its Kubernetes operator and some CLI paths, invoke cosign to check whether an image carries a valid signature before reporting on it. That's a useful integration, but it means signature verification is bolted onto a scanning workflow rather than being the workflow's organizing principle. In practice, teams running Trivy in CI get a vulnerability report and, separately, need to wire up cosign, a policy engine like Kyverno or OPA Gatekeeper, and an admission controller to actually block unsigned or improperly-signed images from reaching a cluster. If any one of those pieces is missing or misconfigured — a common finding in audits — an image can pass its Trivy scan with zero critical CVEs and still be an unsigned, unverified artifact that anyone with registry push access could have swapped in.
What's the real difference between scanning and provenance verification?
Scanning answers "what's known to be wrong with this image's contents," while provenance verification answers "did this image come from where it claims to, unmodified" — and an image can pass one check while completely failing the other. A perfectly clean Trivy scan (zero critical or high CVEs, no exposed secrets, no misconfigured Dockerfile) says nothing about whether the image was built by your CI system or by an attacker who compromised a registry credential and pushed a lookalike image with the same clean scan result. This is exactly the class of attack the SLSA framework (Supply-chain Levels for Software Artifacts, originated at Google and now under OpenSSF) was designed to address, by requiring verifiable provenance attestations — not just clean scan output — before an artifact is trusted. The 3CX supply chain attack in March 2023 is a useful case study here: the compromised desktop app was legitimately code-signed by 3CX's own certificate, because the attacker had compromised the build pipeline itself, not the certificate. Signature verification alone wouldn't have caught that either — you also need to verify that the build pipeline that produced the signature is the one you expect, which is what SLSA provenance and build attestations add on top of a bare signature check.
How do you actually enforce signing at deploy time, not just check it after the fact?
Enforcement means blocking image pulls at the admission layer when a signature or attestation is missing or invalid, not flagging it in a dashboard someone reviews next week. Kubernetes doesn't verify signatures natively; you need an admission controller — Kyverno, OPA Gatekeeper, or Sigstore's own policy-controller — configured with a ClusterImagePolicy or equivalent that rejects any pod spec referencing an image whose digest can't be verified against a trusted identity. The distinction matters because "detected" and "prevented" are operationally very different outcomes: a CVE scan that runs in CI and produces a report can be ignored under deadline pressure (a well-documented failure mode — it's roughly what happened before the 2021 Log4Shell disclosure, when known-vulnerable Log4j versions kept shipping in images long after patches existed). A signature policy enforced at admission has no equivalent bypass path short of someone explicitly disabling the policy, which is itself an auditable, alertable event.
What happens when organizations skip signing entirely?
Without signing, registries function on trust-by-proximity — if an image is present in a registry a team pulls from, it's assumed legitimate, which is precisely the assumption attackers exploit through typosquatting and registry compromise. Docker Hub, npm, and PyPI have each seen incidents where malicious packages sat published under plausible names, accumulating thousands of pulls before removal — npm's event-stream compromise in 2018 shipped a cryptocurrency-stealing payload for roughly two months before a maintainer noticed unfamiliar code in a dependency update. In container registries specifically, the risk compounds because a base image is inherited by every image built on top of it; a single compromised or mislabeled base image can propagate into hundreds of downstream services before anyone traces the source. Signing doesn't prevent someone from publishing a malicious image, but it prevents that image from silently impersonating a trusted one, and it gives incident responders a hard, cryptographic answer to "did this exact artifact come from our pipeline" instead of a guess based on tags and timestamps.
How Safeguard Helps
Safeguard treats signature verification as a gate, not a report. Every image pulled through a Safeguard-protected pipeline is checked against its expected signing identity and Rekor transparency-log entry before it's allowed to progress to build, registry push, or cluster deployment — matching the SLSA provenance model rather than a bare signature check, so a compromised build step that produces a validly-signed but wrong artifact still gets flagged. Safeguard correlates that provenance data with the vulnerability and SBOM findings teams already get from scanners like Trivy, so a security team sees one unified answer — "this image is signed by the expected CI identity, its build provenance matches, and it has zero unresolved criticals" — rather than reconciling scan output in one tool against signature status in another. Policy enforcement is native at the admission layer, configurable per-namespace or per-environment, so unsigned or drift-detected images are blocked automatically rather than relying on a human to notice a dashboard alert. And because every signing and verification event is logged immutably, Safeguard gives compliance and incident-response teams an audit trail that answers exactly the question the XZ Utils and 3CX incidents made painfully relevant: not just "is this image vulnerable," but "did this image actually come from the pipeline we trust."