Container image signing in 2026 is moving from Docker Content Trust, which Docker said fewer than 0.05% of Docker Hub pulls used, to Sigstore cosign and Notary Project Notation, which store signatures beside the image as OCI 1.1 referrers. Notary v1 at notary.docker.io shuts down on 8 December 2026. No public dataset measures what share of images are signed today.
That last sentence matters as much as the first one. A lot has been written about signing adoption, and most of it rests on a single number about a retired tool. This post collects what can actually be measured: the retirement dates, what the OCI 1.1 specifications changed, which registries document support for the referrers API and when, where each signing tool physically puts its signatures and attestations, and how you can sample adoption yourself instead of trusting anyone's estimate.
Key takeaways
- The headline number is about the old tool, not the new ones. Docker wrote on 29 July 2025 that fewer than 0.05% of Docker Hub image pulls used Docker Content Trust. No comparable public figure exists for cosign, Notation or GitHub Artifact Attestations.
- The shutdown date is close. Docker's documentation states the Notary v1 service at notary.docker.io "shuts down completely on December 8, 2026," after brownout windows in July and August. Azure Container Registry removes its own DCT support on 31 March 2028.
- OCI 1.1 gave signatures a standard home. The Image and Distribution specifications v1.1.0 were released on 15 February 2024 and announced on 13 March 2024. They added the
subjectandartifactTypefields, the referrers API, and a fallback tag scheme for registries that lack the API. - Registry support is documented unevenly. Amazon ECR, Azure Container Registry and Harbor document referrers support in their own docs. Google Artifact Registry documents attachments, in Preview, read through the referrers API. The Docker Hub and GitHub Container Registry pages we read do not mention the referrers API at all.
- Three storage models now coexist. Referrers (cosign current docs, Notation, ORAS), digest named tags (older cosign and the OCI fallback), and attestation manifests inside the image index (Docker BuildKit). GitHub Artifact Attestations add a fourth location: GitHub's attestation store, with an option to also push to the registry.
- Signing without verification does nothing. GitHub's own documentation says attestations "only help if consumers verify them." Admission control is where adoption becomes protection.
How much was Docker Content Trust actually used, and why is it being retired?
Docker Content Trust (DCT) was Docker's original image signing feature. It used Notary v1, which implemented The Update Framework, and it was switched on per client with the DOCKER_CONTENT_TRUST=1 environment variable. With the variable set, Docker's documentation says the client only allows tagged images with signatures, or images referenced by explicit content hash, for push, build, create, pull and run.
On 29 July 2025 Docker published its retirement notice. The usage figure in that post is the only measured adoption number in this whole topic: fewer than 0.05% of Docker Hub image pulls used DCT. InfoQ's coverage on 25 August 2025 repeats the same figure and attributes it to Docker.
Docker's stated reasons were practical. The oldest Docker Official Images signing certificates began to expire on 8 August 2025. Docker's post notes that the Docker client does not refresh cached certificates, which makes rotation impractical, and it says the company will implement a different signing solution for Docker Official Images "based on modern, widely used tools." It recommended publishers move to Sigstore or Notation.
What the figure does not tell you:
- It counts pulls, not images, publishers or organisations. A small number of heavily pulled unsigned images can dominate a pull share.
- It measures client side enforcement, because DCT only took effect when the pulling client had the variable set. An image could be signed with DCT and still be pulled without verification.
- It says nothing about cosign or Notation adoption. Teams that moved to those tools years ago would not appear in it at all.
What are the DCT retirement dates, and what breaks if DOCKER_CONTENT_TRUST is set?
The table below lists every date we could confirm, each with its source. Where a date only appears in secondary coverage, we say so.
| Date | Event | Source |
|---|---|---|
| 31 March 2025 | DCT deprecation begins in Azure Container Registry | Microsoft Learn, ACR transition guide |
| 29 July 2025 | Docker announces DCT retirement; fewer than 0.05% of Docker Hub pulls use DCT | Docker blog |
| 8 August 2025 | Oldest Docker Official Images DCT signing certificates begin to expire | Docker blog; InfoQ |
| 30 September 2025 | ACR customers can no longer enable DCT on new registries | InfoQ (secondary; not stated in the Microsoft page we read) |
| July and August 2026 | Brownout windows for notary.docker.io | Docker retired features page (no specific days given) |
| 8 December 2026 | Notary v1 service at notary.docker.io shuts down completely | Docker Engine docs; Docker retired features page |
| 31 March 2028 | DCT completely removed from Azure Container Registry | Microsoft Learn, ACR transition guide |
What breaks depends on whether you are a consumer or a publisher.
Consumers with DOCKER_CONTENT_TRUST=1. Docker's July 2025 post said pulls of Docker Official Images would start to fail as certificates expired, and that docker trust inspect would fail for those images. After 8 December 2026 the Notary v1 service itself is gone, so any trust lookup against notary.docker.io has nothing to answer it. Docker's retired features page is explicit that users who never set the variable and never used docker trust commands are not affected.
Publishers who signed with docker trust sign. Those signatures lived in Notary v1, not in the registry next to the image. When the service shuts down, the signatures stop being retrievable from Docker's infrastructure. They do not migrate to another format. Moving to cosign or Notation means signing again, by digest, with the new tool.
Self hosted Notary v1. Harbor removed its bundled Notary in v2.9.0. The release notes say Harbor "no longer includes Notary in either the user interface or the backend" from that version onward.
What did the OCI Image and Distribution Specifications 1.1 add?
Before OCI 1.1, a registry had no standard way to say "this object is about that image." Tools improvised. Cosign wrote signatures to a tag derived from the image digest. Other tools used separate services entirely, as DCT did with Notary.
The OCI announcement of 13 March 2024 describes the additions. Both specifications were released on 15 February 2024, the first minor releases since Image Spec 1.0.0 in July 2017 and Distribution Spec 1.0.0 in May 2021.
| Addition | Where it lives | What it does |
|---|---|---|
subject field | Image manifest | Points one manifest at another by descriptor, so a signature, SBOM or attestation can declare which image it describes |
artifactType field | Image manifest | Names the type of artifact, so a manifest does not need a dedicated config media type; an empty JSON descriptor is the recommended placeholder |
| Referrers API | Distribution spec | GET /v2/<name>/referrers/<digest> returns an OCI image index of every manifest whose subject is that digest, with each entry's artifactType and annotations |
artifactType filter | Distribution spec | ?artifactType= query parameter; registries that apply it return the OCI-Filters-Applied header |
OCI-Subject header | Distribution spec | Returned on push of a manifest with a subject, which tells the client the registry indexed the relationship |
| Referrers tag schema | Distribution spec | Fallback for registries without the API: the client maintains an index at a tag such as sha256-<hex> |
| 4 MiB manifest guidance | Both | Registries should accept manifests up to 4 MiB and return 413 above their limit |
| Removed artifact manifest | Image spec | A separate artifact manifest type was dropped before release; the image manifest plus artifactType covers the use case |
The distribution specification adds precise rules that matter when you test a registry:
- A registry that supports the API must return
200 OKfor a valid referrers request, even when the list is empty. It must not return404. - A
404from the referrers endpoint tells clients to fall back to the tag schema. - Long lists are paginated with a
Linkheader usingrel="next". - When a client pushes a manifest with a
subjectand gets noOCI-Subjectheader back, it should pull the index at the fallback tag, append the new descriptor and push it back. Two pipelines doing this at once can race, which is why the specification prefers that registries implement the API.
Which registries document referrers API support?
This is the support matrix built only from each registry's own documentation, read on 23 October 2026. "Not documented in the pages we read" means exactly that. It is not a claim that the feature is missing; run the test in the walkthrough below against your own registry before relying on either answer.
| Registry | Referrers API per its own docs | Notes from the same docs | Source |
|---|---|---|---|
| Amazon ECR | Supported | Referrers shown in describe-images and console; replicated on push; cleaned up within 24 hours of subject deletion; EventBridge "ECR Referrer Action" events | AWS Open Source blog, 1 Aug 2024 |
| Azure Container Registry | Supported, except customer managed key (CMK) encrypted registries | ORAS v1.2.3 uses the referrers API by default and falls back to the tag schema on CMK registries | Microsoft Learn, ACR ORAS guide |
| Harbor | Supported from v2.9.0 against Distribution Spec v1.1.0 rc2 | Notation signatures stored as referrers; OCI-Subject header; cosign signatures shown as "accessories" since v2.5 | Harbor v2.9.0 release notes; Harbor signing docs |
| Google Artifact Registry | Attachments (Preview) listed with ORAS using the referrers API | Supported formats page names the OCI spec without a version and does not mention referrers | Google Cloud docs, attachments and supported formats |
| Docker Hub | Not documented in the pages we read | Stores OCI artifacts "by leveraging the config property"; push with ORAS 0.15 or later | Docker Docs, OCI artifacts on Docker Hub |
| GitHub Container Registry | Not documented in the pages we read | Supports Docker V2 Schema 2 and OCI image manifests; GitHub's attestation docs describe push-to-registry | GitHub Docs, Container registry; artifact attestations |
| Quay.io | Not confirmed | Cosign's README lists Red Hat Quay 3.6 and later as tested for cosign signatures; we could not load a Quay page on referrers | Cosign README |
Ranked: registries by the date their referrers support was documented
The ranked table orders registries by the earliest date we could tie to referrers support in the registry operator's own material. Registries without a documented date are listed after the ranked rows and are not ranked.
| Rank | Registry | Date support was documented | What the source says | Source |
|---|---|---|---|---|
| 1 | Harbor | 1 September 2023 (v2.9.0 release; the release page shows "01 Sep" and the year comes from the release series) | Supports Distribution Spec v1.1.0 rc2, a release candidate, not the final 1.1.0 | Harbor GitHub release v2.9.0 |
| 2 | Amazon ECR | 27 June 2024 (launch announcement, as stated in the AWS blog of 1 August 2024) | OCI 1.1 support including the referrers API | AWS Open Source blog |
| unranked | Azure Container Registry | No launch date in the page; current text read 23 October 2026 | Supported except CMK encrypted registries | Microsoft Learn |
| unranked | Google Artifact Registry | No date; attachments marked Preview, page updated 20 October 2026 | Attachments read through the referrers API | Google Cloud docs |
| unranked | Docker Hub, GitHub Container Registry, Quay.io | None found | Not documented in the pages we read | Respective docs |
Two cautions about this ranking. First, the Harbor date is support for a release candidate of the specification, five months before the final release, so it is not like for like with the ECR date. Second, a later documentation date does not mean a registry added support later. Some operators ship quietly and document afterwards. The order reflects documentation, which is the only thing a reader can check.
How do cosign and Notation store signatures?
The two main replacements for DCT take different approaches to keys and identity, but both now lean on the same OCI 1.1 storage model.
Cosign (Sigstore)
The Sigstore documentation for signing containers states that "Signatures use the OCI 1.1 referrer specification." It shows cosign tree $IMAGE to list what is attached to an image and cosign clean $IMAGE to remove signatures, and notes that some registries, Docker Hub among them, do not support deletion.
The cosign README, read the same day, still describes the older layout: signatures stored at a tag derived from the digest, so an image at reg.example.com/ubuntu@sha256:703218... has its signature at reg.example.com/ubuntu:sha256-703218...c3715.sig. The README warns that this layout has a read, append, write race when several signatures are added, and that signatures are not deleted when the image is deleted. The README references cosign 2.6.x; the releases page shows v3.1.4 published on 20 October 2026.
The cosign release notes describe the transition:
- v3.1.1 states the Sigstore bundle format is "now the default output and input for signing and verifying." The v2.6.5 notes say
--new-bundle-format=falsestill produces the old format. - The same v2.6.5 notes say v3.1.x verification supports both formats and tries to detect which one it is given.
- v3.1.2 fixes cosign to include
artifactTypein the OCI 1.1 signature referrer manifest, and v3.1.4 fixes writing referrers when an image index has attestations. - v3.1.1 deprecates the "OCI Referrers" flags for removal in v4.
What this means in practice: an image signed in 2023 most likely carries a .sig tag, and an image signed with a current cosign carries a referrer. A verifier needs to handle both during the transition. Keyless signing is the cosign default: cosign sign $IMAGE obtains a short lived certificate through an OIDC login with Google, GitHub or Microsoft, and the signing event is recorded in the Rekor transparency log. Keys can also come from a local file or from KMS URIs such as awskms://, gcpkms://, azurekms:// and hashivault://.
On registry coverage, the cosign README lists more than a dozen registries it has been tested against, including Amazon ECR, Google Artifact Registry, Docker Hub, Azure Container Registry, GitHub Container Registry, Harbor and Red Hat Quay 3.6 and later. Being on that list means cosign signatures work there; it does not by itself mean the registry implements the referrers API.
Notation (Notary Project)
Notation is the command line tool of the Notary Project, which its README describes as a CNCF Incubating project. It signs with X.509 certificates, typically issued by your own CA or held in a cloud key service through a plugin, and verifies against a trust policy and trust store you configure.
Notation writes each signature as an OCI manifest with a subject pointing at the image. Whether that manifest is found through the referrers API or through the fallback tag depends on the version and a flag. The AWS walkthrough of ECR's OCI 1.1 support, published 1 August 2024, signs with notation sign --force-referrers-tag=false so that Notation uses the referrers API, and notes that this support arrived in Notation 1.2.0, then a pre-release. Microsoft's ACR guidance recommends Notation with Azure Key Vault and documents verification in Azure Pipelines, GitHub Actions and on AKS through Ratify and Azure Policy.
Where signatures and attestations physically live
| Producer | What it writes | Where it lives | Behaviour without referrers API |
|---|---|---|---|
| Cosign, older releases | Signature manifest | Tag sha256-<hex>.sig in the same repository | Not affected; never used the API |
| Cosign, current releases | Sigstore bundle as a referrer | OCI 1.1 referrer with subject | Falls back to the OCI tag schema per the spec |
| Notation | Signature manifest (JWS or COSE envelope) | OCI 1.1 referrer with subject | Referrers tag schema; on older Notation the tag was the default |
ORAS attach | Any artifact (SBOM, scan report) | OCI 1.1 referrer with subject | Referrers tag schema (ACR documents this for CMK registries) |
| Docker BuildKit | SLSA provenance (mode=min by default) and optional SBOM | Attestation manifests referenced from the image index | Not affected; lives inside the index |
Docker BuildKit with oci-artifact | Same attestations | Manifest with artifactType and subject | Depends on registry and client |
| GitHub Artifact Attestations | Sigstore bundle with SLSA provenance or SBOM predicate | GitHub attestation store; optionally pushed to the image registry | Registry push depends on registry |
| Docker Content Trust | TUF metadata | Notary v1 server, outside the registry | Service ends 8 December 2026 |
What do GitHub Artifact Attestations store, and where?
GitHub made Artifact Attestations generally available on 25 June 2024. The changelog describes them as Sigstore powered signed attestations that link an artifact to the GitHub Actions build that produced it, working for both public and private repositories, verified with gh attestation verify.
GitHub's concept documentation explains the storage split:
- Public repositories use the Sigstore Public Good Instance. A copy of the bundle is stored with GitHub and the signing event is written to the public, append only transparency log.
- Private repositories use GitHub's own Sigstore instance, which shares the Public Good codebase but "only federates with GitHub Actions" and has no transparency log.
For container images, the attest action can also push the attestation to the registry. GitHub's how to page shows push-to-registry: true on the attest step, with the fully qualified image name as subject-name (the docs warn not to include a tag) and the image digest as subject-digest. With the artifact-metadata: write permission the action also records storage records on the organisation's linked artifacts page.
On SLSA, GitHub's documentation says attestations alone provide SLSA v1.0 Build Level 2, and that Build Level 3 is reachable by running the build in a reusable workflow shared across repositories, which isolates the build from the calling workflow.
GitHub also states the limit plainly: attestations do not guarantee that an artifact is secure. They prove where and how it was built. Deciding whether to accept it is the consumer's job.
Which major projects sign their images, and how can you verify one?
Kubernetes is the clearest documented example. Its "Verify Signed Kubernetes Artifacts" task page says the release process signs binary artifacts, the SBOM and container images with cosign keyless signing, a feature marked beta since Kubernetes v1.26. The page publishes the exact identities to verify against:
| Artifact | Certificate identity | OIDC issuer |
|---|---|---|
| Container images | krel-trust@k8s-releng-prod.iam.gserviceaccount.com | https://accounts.google.com |
| Binaries and SBOM | krel-staging@k8s-releng-prod.iam.gserviceaccount.com | https://accounts.google.com |
Verifying one control plane image takes one command. Substitute the version you run:
cosign verify registry.k8s.io/kube-apiserver-amd64:v1.37.0 \
--certificate-identity krel-trust@k8s-releng-prod.iam.gserviceaccount.com \
--certificate-oidc-issuer https://accounts.google.com \
| jq .
The page also shows a loop that pulls the image list from the release SBOM at sbom.k8s.io and verifies every control plane image, and it recommends pinning images by digest in Pod manifests after verification. For images outside the control plane, such as the conformance image, it points to the Sigstore policy controller for enforcement at deploy time.
Pinning both flags matters. Cosign 2.0 and later require --certificate-identity and --certificate-oidc-issuer for keyless verification. Without them, "verified" only means "signed by someone with a valid certificate," which any GitHub or Google account can obtain.
Is there any public measure of what share of images are signed?
No. Docker's 0.05% figure covers DCT pulls only. No registry operator we read publishes the share of its images or pulls that carry a cosign or Notation signature, and we found no published count of container image entries in Rekor that would let anyone compute a share. If you see a percentage for "signed images" without a stated dataset, sample, date and method, treat it as unverified.
You can sample adoption yourself in a few minutes. The script below takes a list of image references, resolves each to a digest, checks for a legacy cosign signature tag, and counts OCI 1.1 referrers. It assumes references in registry/repo:tag form without a port.
#!/usr/bin/env bash
# sample-signing.sh: count signatures and referrers for a list of images
# usage: ./sample-signing.sh images.txt > results.csv
set -u
echo "image,digest,legacy_sig_tag,referrer_count"
while read -r image; do
[ -z "$image" ] && continue
digest=$(crane digest "$image" 2>/dev/null) || { echo "$image,error,,"; continue; }
repo="${image%:*}"
hex="${digest#sha256:}"
if crane manifest "${repo}:sha256-${hex}.sig" >/dev/null 2>&1; then
legacy=yes
else
legacy=no
fi
count=$(oras discover --format json "${repo}@${digest}" 2>/dev/null \
| jq '[.. | objects | select(has("artifactType"))] | length' 2>/dev/null)
echo "${image},${digest},${legacy},${count:-0}"
done < "$1"
Older ORAS releases use -o json instead of --format json, and the JSON layout differs between versions, so inspect one result by hand before trusting the counts. A referrer count above zero means something is attached; it does not tell you whether that something is a valid signature from an identity you trust. For that, run cosign verify or notation verify with explicit identities.
Walkthrough: from DCT to verified, admission controlled images
The steps below move a team off DCT, sign by digest, attach an SBOM, and enforce at deploy time. Replace the example names with your own.
Step 1: find every place DCT is still switched on
# Local shell and CI runners
env | grep DOCKER_CONTENT_TRUST
# CI definitions in a repository
grep -rn "DOCKER_CONTENT_TRUST\|docker trust" \
.github/workflows .gitlab-ci.yml azure-pipelines.yml bitbucket-pipelines.yml 2>/dev/null
# Switch it off where found (Docker's own guidance)
unset DOCKER_CONTENT_TRUST
On Azure Container Registry, Microsoft documents disabling DCT on the registry as well:
az acr config content-trust update -r myregistry --status disabled
Step 2: test whether your registry implements the referrers API
IMAGE=registry.example.com/team/app:1.4.2
DIGEST=$(crane digest "$IMAGE")
# ORAS falls back to the tag schema automatically; the tree shows what is attached
oras discover --format tree "registry.example.com/team/app@${DIGEST}"
# Direct check: 200 means the API exists, 404 means it does not
curl -s -o /dev/null -w "%{http_code}\n" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Accept: application/vnd.oci.image.index.v1+json" \
"https://registry.example.com/v2/team/app/referrers/${DIGEST}"
Per the distribution specification, a registry that supports the API returns 200 with an image index, even an empty one. Write the result down with the date, because registries add support without announcement.
Step 3: sign by digest in CI with cosign keyless
# .github/workflows/release.yml (excerpt)
permissions:
contents: read
packages: write
id-token: write # lets cosign obtain a short lived signing certificate
jobs:
build-sign:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: sigstore/cosign-installer@v3 # pin to a commit SHA in production
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- id: build
uses: docker/build-push-action@v6
with:
push: true
tags: ghcr.io/example-org/app:${{ github.sha }}
sbom: true
provenance: mode=max
- name: Sign the pushed digest
run: cosign sign --yes ghcr.io/example-org/app@${{ steps.build.outputs.digest }}
Always sign the digest, never a tag. A tag can be moved to different content after signing; a digest cannot.
Step 4: verify with an exact identity
cosign verify ghcr.io/example-org/app@sha256:<digest> \
--certificate-identity "https://github.com/example-org/app/.github/workflows/release.yml@refs/heads/main" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"
Step 5: attach and verify an SBOM attestation
syft ghcr.io/example-org/app@sha256:<digest> -o spdx-json > sbom.spdx.json
cosign attest --yes --type spdxjson \
--predicate sbom.spdx.json \
ghcr.io/example-org/app@sha256:<digest>
cosign verify-attestation --type spdxjson \
--certificate-identity "https://github.com/example-org/app/.github/workflows/release.yml@refs/heads/main" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
ghcr.io/example-org/app@sha256:<digest>
If you built with BuildKit attestations, inspect what is already in the index before adding more:
docker buildx imagetools inspect ghcr.io/example-org/app:latest \
--format '{{ json .Provenance }}'
Step 6 (alternative): sign with Notation and a trust policy
# Test key and certificate for local trials only; use your CA or a KMS plugin in production
notation cert generate-test --default "example.io"
notation sign --signature-format cose registry.example.com/team/app@sha256:<digest>
# On Amazon ECR, the AWS walkthrough forces use of the referrers API:
notation sign --force-referrers-tag=false <account>.dkr.ecr.<region>.amazonaws.com/app@sha256:<digest>
Verification needs a trust policy that names the registry scope and the trust store:
{
"version": "1.0",
"trustPolicies": [
{
"name": "team-app",
"registryScopes": ["registry.example.com/team/app"],
"signatureVerification": { "level": "strict" },
"trustStores": ["ca:example.io"],
"trustedIdentities": ["*"]
}
]
}
notation policy import ./trustpolicy.json
notation verify registry.example.com/team/app@sha256:<digest>
In production, replace "*" in trustedIdentities with the specific certificate subject you sign with.
Step 7: GitHub Artifact Attestations as a parallel record
permissions:
id-token: write
contents: read
attestations: write
packages: write
steps:
- name: Generate artifact attestation
uses: actions/attest@v4
with:
subject-name: ghcr.io/example-org/app
subject-digest: ${{ steps.build.outputs.digest }}
push-to-registry: true
gh attestation verify oci://ghcr.io/example-org/app:1.4.2 -R example-org/app
Step 8: enforce at admission
Signing only changes outcomes when the cluster refuses what fails verification. The Kubernetes documentation points to the Sigstore policy controller for this. A policy that admits only images signed by your release workflow looks like this; check field names against the current policy controller documentation before you apply it:
apiVersion: policy.sigstore.dev/v1beta1
kind: ClusterImagePolicy
metadata:
name: require-release-signature
spec:
images:
- glob: "ghcr.io/example-org/**"
authorities:
- keyless:
url: https://fulcio.sigstore.dev
identities:
- issuer: https://token.actions.githubusercontent.com
subjectRegExp: "^https://github.com/example-org/.+/.github/workflows/release.yml@refs/heads/main$"
kubectl label namespace prod policy.sigstore.dev/include=true
On Azure, Microsoft documents Ratify with Azure Policy for Notation signatures on AKS. On Harbor, a project administrator can enforce content trust so that unsigned artifacts cannot be pulled from that project. Whichever you choose, roll out in audit or warn mode first, collect a week of results, then switch to deny.
How do signing and provenance tie into admission control?
Signing answers "who produced this digest." Provenance answers "how and from what source was it built." Admission control is where both become a decision.
A sensible policy checks three things in order:
- Identity. The signature chains to an identity you expect: a specific workflow path and branch for keyless signing, or a specific certificate subject for Notation. A wildcard identity is a policy that admits anyone.
- Provenance. The SLSA provenance names your repository, the expected builder and a commit you can trace. GitHub documents Build Level 2 for plain attestations and Level 3 with a reusable workflow.
- Content. The attached SBOM is present, current for that digest, and passes your vulnerability and license rules.
Two operational details trip teams up. First, signatures must travel with images. ECR documents that referrers replicate with their subject on push, and ACR documents copying a whole artifact graph with oras copy -r; Harbor's signing docs say replication carries cosign signatures only on manual and scheduled triggers, not on event based ones. Second, mirrors and pull through caches may not copy referrers at all, so an image that verifies at the source can fail at the mirror. Test the path your nodes actually pull from.
Where do sources disagree?
- OCI 1.1 release date. Many articles give 13 March 2024. The OCI post published on that date says the specifications were released on 15 February 2024 and announced on 13 March.
- DCT brownout dates. Third party articles list specific days in July and August 2026. Docker's own pages we read give only the months.
- Notary v1 shutdown. InfoQ (25 August 2025) gives no Docker shutdown date and cites 31 March 2028 only for Azure. Docker's documentation now states 8 December 2026 for notary.docker.io. These are different services with different dates.
- How cosign stores signatures. The Sigstore docs say signatures use OCI 1.1 referrers; the cosign README still describes
.sigtags and references 2.6.x. Both are true for different versions.
How we measured
Datasets and dates. The only adoption figure in this post is Docker's statement of 29 July 2025 that fewer than 0.05% of Docker Hub image pulls used DCT, repeated by InfoQ on 25 August 2025. Docker did not publish the measurement window, the absolute pull count, or whether the figure covers all pulls or only pulls of signed repositories. Every other fact comes from specifications, release notes and documentation pages, all read on 23 October 2026.
What each source counts. Docker's figure counts pulls by clients with DCT enabled. Registry documentation describes capability, not usage. Cosign's README lists registries tested for cosign compatibility, which is a different property from referrers API support. GitHub's attestation docs describe storage, not volume. None of these can be added together, averaged or turned into a share of signed images.
Support matrix method. For each registry we read the operator's own documentation for the referrers API, the subject field and supply chain artifacts. Where a page did not mention the feature, we wrote "not documented in the pages we read" rather than "unsupported." We did not run live tests against any registry for this post; the walkthrough shows how to do so.
Ranked table method. Registries are ordered by the earliest date we could tie to referrers support in the operator's own material. Harbor's date comes from its v2.9.0 release; ECR's date is the launch date stated in AWS's August 2024 blog. Registries with no date are listed but not ranked.
What we excluded. We did not use vendor research reports from image security or hardened image vendors, survey estimates without a published method, or brownout days that appear only in secondary coverage.
Common mistakes
Reading the 0.05% as signing adoption. It is DCT pull share on Docker Hub. It does not measure cosign, Notation or GitHub attestations.
Treating "works with cosign" as "supports referrers." Cosign worked on many registries long before OCI 1.1 because it used tags. Check the referrers endpoint directly.
Signing tags instead of digests. A signature on a tag says nothing about what the tag points to next week.
Verifying without an identity. cosign verify with only an issuer, or Notation with trustedIdentities set to "*", accepts signatures from people you do not know.
Assuming signatures follow images. Promotion scripts that copy by tag, pull through caches and some replication triggers leave signatures at the source. Copy the artifact graph, then verify at the destination.
Deleting fallback tags as clutter. On a registry without the referrers API, the sha256-<hex> tags are the index of your signatures. Cleanup jobs that remove "unknown" tags can break verification.
Leaving DOCKER_CONTENT_TRUST=1 in a CI image. Once notary.docker.io is gone, trust lookups against it have no service to answer them. Find and remove the variable now rather than in December.
FAQ
Is Docker Content Trust deprecated?
Yes. Docker announced its retirement on 29 July 2025, and its documentation states the Notary v1 service at notary.docker.io shuts down completely on 8 December 2026. Azure Container Registry removes DCT on 31 March 2028.
What happens if DOCKER_CONTENT_TRUST=1 is still set?
Docker said in July 2025 that pulls of Docker Official Images would start failing as certificates expired. Docker's workaround is to unset the variable. After 8 December 2026 the Notary v1 service is gone entirely.
What is the OCI referrers API?
It is the endpoint GET /v2/<name>/referrers/<digest>, added in OCI Distribution Spec 1.1, that returns every manifest whose subject points at a given digest. It is how tools find signatures, SBOMs and attestations attached to an image.
Does Docker Hub support the OCI referrers API?
Docker's OCI artifacts page that we read does not mention it. Test it yourself: request the referrers endpoint for an image digest and check for a 200 (supported) or 404 (not supported) response.
Where does cosign store signatures?
Older cosign releases store them at a tag named after the image digest with a .sig suffix. Current Sigstore documentation says signatures use the OCI 1.1 referrer specification, and cosign v3.1.1 made the Sigstore bundle format the default.
Are GitHub artifact attestations stored in the registry?
By default they are stored with GitHub, and for public repositories the signing event is also logged in Sigstore's public transparency log. Setting push-to-registry: true in the attest action also pushes the attestation to the image registry.
What percentage of container images are signed?
No public dataset answers this. The only published figure is Docker's DCT pull share. You can sample a list of images yourself with crane, oras discover and cosign verify.
How do I verify a Kubernetes image signature?
Run cosign verify against the image with --certificate-identity krel-trust@k8s-releng-prod.iam.gserviceaccount.com and --certificate-oidc-issuer https://accounts.google.com, as documented on kubernetes.io.
Related reading
- Docker Content Trust is being retired: what should you use instead?
- Attach an SBOM and signature to an image with OCI referrers
- Where do image attestations live in a registry?
- How to check a public image has provenance and SBOM attestations
- Cosign v3 migration guide
Fix it without waiting for upstream
A signature proves who built an image; it does not make a vulnerable base layer safe. Once your images are signed and attested, the next gap is what is inside them, and how long it takes to get a fixed version shipping.
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.
3. Gold Registry: start from components that are already fixed
registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | The Gold scan GitHub Action in CI, plus Safeguard policies and gates |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch (early access) |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
Where Safeguard fits
Safeguard scans container images, repositories and SBOM files (safeguard scan --image <name>, --dir ., --sbom <file>), matches components against vulnerability databases, and shows which projects contain a given component and version. Each project has Attestation and Provenance views next to its dependencies and vulnerabilities, and policies and gates evaluated in the platform can block, warn or require approval before a release moves on.
What Safeguard does not do: it does not replace your registry's referrers support, it does not run the Notary v1 service, and it does not decide for you which signing identities to trust. Those choices stay in your pipeline and your admission policy. Gold Registry images are Sigstore signed and carry SLSA L3 or higher provenance, so they fit the same cosign verify and admission flow described above.
To try it, download Safeguard and follow the CLI docs.
See how Safeguard would help
The first demo is a real Safeguard CLI session. It installs the CLI, opens the interactive terminal, and asks it to fix a lodash CVE in a repository: it reads the finding and the advisory, asks before each command, edits package.json to lodash 4.17.21, runs npm install and npm test with approval, and pushes nothing. The same loop applies after you sign an image and find a vulnerable dependency inside it: fix the dependency, rebuild, and sign the new digest.
Click through it at your own pace, or open it full screen.
The second demo sets up the local runner on your own machine, approves it with its device code, and scans from the terminal. For signing work this is where image scans run next to your build, so the SBOM you attach as an attestation and the scan you gate on describe the same digest.
Click through it at your own pace, or open it full screen.
The third demo connects Claude to the Safeguard MCP server with OAuth and shows how to choose which tools Claude can use. It is useful when a platform team wants to ask questions across projects, such as which images still carry a vulnerable component, without opening each project by hand.
Click through it at your own pace, or open it full screen.
Quick check
A registry returns 404 for GET /v2/team/app/referrers/sha256:... What does that mean?
Under the OCI Distribution Spec 1.1, a 404 tells the client the registry does not implement the referrers API. Clients should fall back to the referrers tag schema, a tag named sha256- followed by the digest's hex value. A registry that supports the API returns 200, even when nothing is attached.
Is the 0.05% figure a measure of how many container images are signed?
No. Docker's figure is the share of Docker Hub image pulls that used Docker Content Trust, stated on 29 July 2025. It does not count cosign, Notation or GitHub attestations, and no public dataset measures the share of signed images overall.
Sources
- Docker Docs: Content trust in Docker
- Docker Docs: Retired features
- Docker blog: Retiring Docker Content Trust (29 July 2025)
- InfoQ: Docker Content Trust retired (25 August 2025)
- Docker Docs: OCI artifacts on Docker Hub
- Docker Docs: Build attestations
- OCI: Image and Distribution 1.1 released (13 March 2024)
- OCI Distribution Specification
- AWS Open Source blog: OCI Image and Distribution 1.1 support in Amazon ECR (1 August 2024)
- Microsoft Learn: Transition from Docker Content Trust to Notary Project in ACR
- Microsoft Learn: Manage OCI artifacts and supply chain artifacts with ORAS in ACR
- Google Cloud: Artifact Registry supported formats
- Google Cloud: Manage metadata with attachments
- GitHub Docs: Working with the Container registry
- GitHub changelog: Artifact attestations is generally available (25 June 2024)
- GitHub Docs: Artifact attestations concepts
- GitHub Docs: Using artifact attestations to establish provenance for builds
- Harbor Docs: Sign images
- Harbor v2.9.0 release notes
- Sigstore Docs: Signing containers
- Cosign README
- Cosign releases
- Notation README
- Kubernetes: Verify signed Kubernetes artifacts
Last reviewed: 23 October 2026. Registry support and retirement timelines change; check each registry's documentation for the latest status.