Safeguard
Supply Chain Security•

Container Image Signing and Provenance in 2026: The Adoption Data

Fewer than 0.05% of Docker Hub pulls used Docker Content Trust. What replaces it, which registries document OCI 1.1 referrers, and how to verify.

Safeguard Security Team
35 min read

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 subject and artifactType fields, 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.

DateEventSource
31 March 2025DCT deprecation begins in Azure Container RegistryMicrosoft Learn, ACR transition guide
29 July 2025Docker announces DCT retirement; fewer than 0.05% of Docker Hub pulls use DCTDocker blog
8 August 2025Oldest Docker Official Images DCT signing certificates begin to expireDocker blog; InfoQ
30 September 2025ACR customers can no longer enable DCT on new registriesInfoQ (secondary; not stated in the Microsoft page we read)
July and August 2026Brownout windows for notary.docker.ioDocker retired features page (no specific days given)
8 December 2026Notary v1 service at notary.docker.io shuts down completelyDocker Engine docs; Docker retired features page
31 March 2028DCT completely removed from Azure Container RegistryMicrosoft 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.

AdditionWhere it livesWhat it does
subject fieldImage manifestPoints one manifest at another by descriptor, so a signature, SBOM or attestation can declare which image it describes
artifactType fieldImage manifestNames the type of artifact, so a manifest does not need a dedicated config media type; an empty JSON descriptor is the recommended placeholder
Referrers APIDistribution specGET /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 filterDistribution spec?artifactType= query parameter; registries that apply it return the OCI-Filters-Applied header
OCI-Subject headerDistribution specReturned on push of a manifest with a subject, which tells the client the registry indexed the relationship
Referrers tag schemaDistribution specFallback for registries without the API: the client maintains an index at a tag such as sha256-<hex>
4 MiB manifest guidanceBothRegistries should accept manifests up to 4 MiB and return 413 above their limit
Removed artifact manifestImage specA 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 OK for a valid referrers request, even when the list is empty. It must not return 404.
  • A 404 from the referrers endpoint tells clients to fall back to the tag schema.
  • Long lists are paginated with a Link header using rel="next".
  • When a client pushes a manifest with a subject and gets no OCI-Subject header 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.

RegistryReferrers API per its own docsNotes from the same docsSource
Amazon ECRSupportedReferrers shown in describe-images and console; replicated on push; cleaned up within 24 hours of subject deletion; EventBridge "ECR Referrer Action" eventsAWS Open Source blog, 1 Aug 2024
Azure Container RegistrySupported, except customer managed key (CMK) encrypted registriesORAS v1.2.3 uses the referrers API by default and falls back to the tag schema on CMK registriesMicrosoft Learn, ACR ORAS guide
HarborSupported from v2.9.0 against Distribution Spec v1.1.0 rc2Notation signatures stored as referrers; OCI-Subject header; cosign signatures shown as "accessories" since v2.5Harbor v2.9.0 release notes; Harbor signing docs
Google Artifact RegistryAttachments (Preview) listed with ORAS using the referrers APISupported formats page names the OCI spec without a version and does not mention referrersGoogle Cloud docs, attachments and supported formats
Docker HubNot documented in the pages we readStores OCI artifacts "by leveraging the config property"; push with ORAS 0.15 or laterDocker Docs, OCI artifacts on Docker Hub
GitHub Container RegistryNot documented in the pages we readSupports Docker V2 Schema 2 and OCI image manifests; GitHub's attestation docs describe push-to-registryGitHub Docs, Container registry; artifact attestations
Quay.ioNot confirmedCosign's README lists Red Hat Quay 3.6 and later as tested for cosign signatures; we could not load a Quay page on referrersCosign 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.

RankRegistryDate support was documentedWhat the source saysSource
1Harbor1 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.0Harbor GitHub release v2.9.0
2Amazon ECR27 June 2024 (launch announcement, as stated in the AWS blog of 1 August 2024)OCI 1.1 support including the referrers APIAWS Open Source blog
unrankedAzure Container RegistryNo launch date in the page; current text read 23 October 2026Supported except CMK encrypted registriesMicrosoft Learn
unrankedGoogle Artifact RegistryNo date; attachments marked Preview, page updated 20 October 2026Attachments read through the referrers APIGoogle Cloud docs
unrankedDocker Hub, GitHub Container Registry, Quay.ioNone foundNot documented in the pages we readRespective 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=false still 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 artifactType in 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

ProducerWhat it writesWhere it livesBehaviour without referrers API
Cosign, older releasesSignature manifestTag sha256-<hex>.sig in the same repositoryNot affected; never used the API
Cosign, current releasesSigstore bundle as a referrerOCI 1.1 referrer with subjectFalls back to the OCI tag schema per the spec
NotationSignature manifest (JWS or COSE envelope)OCI 1.1 referrer with subjectReferrers tag schema; on older Notation the tag was the default
ORAS attachAny artifact (SBOM, scan report)OCI 1.1 referrer with subjectReferrers tag schema (ACR documents this for CMK registries)
Docker BuildKitSLSA provenance (mode=min by default) and optional SBOMAttestation manifests referenced from the image indexNot affected; lives inside the index
Docker BuildKit with oci-artifactSame attestationsManifest with artifactType and subjectDepends on registry and client
GitHub Artifact AttestationsSigstore bundle with SLSA provenance or SBOM predicateGitHub attestation store; optionally pushed to the image registryRegistry push depends on registry
Docker Content TrustTUF metadataNotary v1 server, outside the registryService 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:

ArtifactCertificate identityOIDC issuer
Container imageskrel-trust@k8s-releng-prod.iam.gserviceaccount.comhttps://accounts.google.com
Binaries and SBOMkrel-staging@k8s-releng-prod.iam.gserviceaccount.comhttps://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:

  1. 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.
  2. 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.
  3. 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 .sig tags 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

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 situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull 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

Last reviewed: 23 October 2026. Registry support and retirement timelines change; check each registry's documentation for the latest status.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.