Use both, because they stop different things. Registry tag immutability prevents a tag from being overwritten after it is pushed. Digest pinning at admission makes the cluster run one exact image regardless of what any tag says. The first protects your registry, the second protects your deploys.
Definitions
A tag is a movable label such as 1.4. A digest is a hash of the image content. The Kubernetes documentation puts it plainly: tags can be moved to point to different images, but digests are fixed.
Tag immutability is a registry feature. For example, Amazon ECR's documentation says that after you turn it on, pushing an image with a tag that already exists returns an ImageTagAlreadyExistsException. It applies to all tags in the repository, with optional exclusion filters if you need a few mutable tags such as latest.
What each control prevents
| Threat | Registry immutability | Digest pinning at admission |
|---|---|---|
| Someone re-pushes a tag with different content | Blocked at the registry | Not relevant, the digest does not move |
| A manifest still says app:1.4 and the tag was changed elsewhere | Blocked only if that registry enforces it | Blocked, the pod resolves to a fixed digest |
| A registry without immutability, or a mirror, is used | Not covered | Covered |
| Developers ship a tag by habit | Not covered, tags still allowed | Policy can reject tag only references |
| Auditor asks what exactly ran on a date | Partly answered | Answered by the digest |
Neither control tells you the image is free of vulnerabilities. They tell you the image did not silently change.
Option A: turn on registry immutability
Set it per repository. In ECR that is a repository setting, and the documentation shows both console and CLI paths. Check how your registry treats the setting, since behavior and exclusions differ by product.
Watch out for build systems that deliberately re-push a rolling tag. They will start failing, which is the point, but plan the migration. Move them to unique tags, such as a commit hash, before you flip the switch.
Option B: require digests at admission
Kyverno's image verification documentation describes two relevant options in a verifyImages rule: mutateDigest converts tags to digests for matching images, and verifyDigest enforces that digests are used. It notes that a digest helps ensure the deployed version is the same one that was scanned and verified. You can write a similar check yourself in a ValidatingAdmissionPolicy that rejects references without an at sign digest.
Mutating tags to digests at admission is friendly to developers, since manifests stay readable. The tradeoff is that the manifest in Git no longer matches what the cluster stores, so make sure your GitOps tool handles that difference without flapping.
A sensible order
- Inventory which images in your clusters are referenced by tag only.
- Move build output to unique tags, then enable registry immutability.
- Add digest enforcement in Warn mode, then Deny.
- Record the digest in your release notes or deployment record so rollbacks are exact.
Where Safeguard fits
Safeguard's SBOM and dependency scanning ties findings to what you actually build, and its policies and gates can hold a release that does not meet your rules. Pinning tells you which bytes shipped, scanning tells you what is in them. A free scan shows the second half.
Try it yourself
Click through it at your own pace, or open it full screen. Notice that every finding is tied to a specific image, which is why a fixed digest matters.
Quick check
Is a version tag like 1.4 safe to rely on?
Only if the registry enforces immutability and you trust everyone with push rights. A digest does not depend on either.
Do digests break rollbacks?
No, they make them exact. You redeploy the previous digest and get the same bytes.
Sources
Last reviewed: 19 October 2026.