Virtualization · Image Supply Chain

Referrers, Attachments, and the Artifact Graph

How a registry indexes artifacts by the digest they describe, why the fallback naming convention is spoofable, and how a verifier discovers signatures and SBOMs without being told where to look.

A signature is useless if the verifier cannot find it. The same is true of a software bill of materials, a vulnerability report, or a provenance statement. All of these are artifacts about another artifact, and the registry protocol originally had no way to express that relationship. The history of how that gap was closed, and what remains awkward about it, explains a great deal of the inconsistency in how image verification tooling behaves across registries.

The original workaround was a naming convention

Before there was an API for it, the convention was to store related artifacts under a derived repository name. A signature for example/api at digest sha256:abc... would be pushed as a tag inside a repository named example/api with a suffix such as sha256-abc....sig, and a verifier would compute that name from the digest and attempt a pull.

The convention has properties that are convenient and one that is fatal. Convenient: it works on any registry, because it uses only tags and manifests. Fatal: the repository name is a namespace that anyone with push access can create, and the derived name for a given digest is predictable. An attacker who can push to a repository whose name collides with the derived name can publish artifacts that a verifier will discover and, if the verifier’s policy is weak, accept. More mundanely, a verifier that only knows one convention cannot see signatures stored under another, so coverage depends on which tools produced the artifacts.

The convention also loses the artifact type. A tag like sha256-abc....sig says “signature” only by suffix; there is no machine-readable statement of what kind of document is inside, and no way to attach two artifacts of the same kind without inventing another suffix.

The referrers API inverts the index

The referrers API makes the relationship a first-class registry concept. When a manifest is pushed with a subject field naming another manifest’s digest, the registry records the new manifest in an index for that subject. A verifier then issues a single request (a GET on the referrers endpoint for the subject digest) and receives an index whose entries are descriptors for every manifest that names it.

{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.index.v1+json",
  "manifests": [
    {
      "mediaType": "application/vnd.example.signature.v1+json",
      "digest": "sha256:7c1d...",
      "size": 912,
      "artifactType": "application/vnd.example.signature.v1+json",
      "annotations": {
        "org.opencontainers.image.created": "2025-09-01T10:00:00Z"
      }
    }
  ]
}

Three details carry the weight. The response is an index, so it is paged and filtered like any other index, and a client that assumes all entries fit in one response misses artifacts when the list grows. The artifactType field names the type of the referring artifact without requiring the client to fetch and parse it, which is what allows a verifier to select signatures from a mixed list of signatures, SBOMs, and scan reports. And the subject field on the pushed manifest is what creates the edge, so an artifact pushed without it is invisible to the referrers query no matter what annotations it carries.

The registry’s obligation is to maintain that index as manifests are pushed and deleted. This is where implementations diverge. A registry may support referrers for some media types and not others, may not index manifests whose subject points at a digest it does not itself hold, and may lag behind on deletion. The specification allows a registry to answer the referrers request with a 404 or an empty index when it does not support the feature, and clients must distinguish “no referrers” from “feature absent” to decide whether to fall back to the tag convention.

Falling back is a downgrade, and should be treated as one

A client that falls back to tag-based discovery when referrers are unavailable is making a choice with security consequences. Tag-based discovery reads from a namespace where anyone with push rights can create entries, and where the association between an artifact and a subject digest is asserted only by the repository name.

Two mitigations are available and both are partial. The first is to verify the artifact’s own content: a signature envelope names a payload digest, and a verifier must confirm that the payload digest is the image digest being deployed. Under the tag convention, the repository name is a hint, and the payload is the claim. A verifier that checks the payload rather than trusting the name is safe against a wrong association, though not against a missing one. The second is to scope discovery to repositories the verifier trusts, which turns the fallback into a policy decision about who may publish associations.

Neither mitigation restores the property the referrers API provides, which is that the association is recorded by the registry as part of accepting the push. A tag-based association is not recorded anywhere authoritative; it is inferred.

SBOMs make the graph wide

A software bill of materials attached to an image lists the packages inside it, with versions and often with their own identifiers. In SPDX and CycloneDX, the document is a structured graph of components and relationships, and its size scales with the dependency count: a modest application image with a language runtime can carry thousands of components, and the document can be larger than the image config by orders of magnitude.

Attaching an SBOM as a referrer rather than embedding it in the image has two effects. It keeps the image digest stable when the SBOM is regenerated, which matters because the SBOM is derived data that changes as scanners improve. And it means the SBOM’s own integrity is a separate concern: it is content addressed like any blob, and its association to the image is the referrers edge. A verifier that trusts an SBOM because it was found under the right subject digest has trusted the registry’s index, not the SBOM’s producer. If the SBOM’s authorship matters, it needs its own signature.

The predicate question recurs here. An SBOM describes the packages in an image, but the mapping from packages to image requires unpacking the layers, and the SBOM is a claim about that unpacked content rather than a derivation from the digest. Two SBOMs for the same image digest can disagree, and neither is verifiable from the digest alone. What can be checked is that both name the same subject, which is a consistency check rather than a correctness one.

The graph is not a tree, and cycles are possible

Artifacts can refer to artifacts that refer to artifacts. A signature envelope is itself a manifest with a subject; an attestation about a signature is possible; an SBOM can be signed, producing an artifact that refers to the SBOM, which refers to the image. A verifier walking this graph must bound the traversal, both for cost and for termination.

The traversal cost is multiplicative. A subject with r referrers, each with r’ referrers, costs O(r·r’) fetches before any content is examined, and a registry that pages results at a hundred entries per response adds round trips at every level. Verifiers in practice fix a depth (two levels covers image → signature and image → SBOM → signature) and filter by artifactType before fetching, since the type is in the descriptor and does not require a download.

Cycles are possible because the subject field is just a digest and nothing prevents two artifacts from naming each other. A registry that indexes both will happily return each as a referrer of the other. Without a visited set keyed on digest, a naive walk does not terminate.

Deletion leaves dangling edges

When a referring artifact is deleted, the registry removes it from the index for its subject. When the subject is deleted, the referring artifacts remain, now pointing at a digest with no manifest. Their content is still fetchable by digest, since blobs are independent of the manifests that name them, so a verifier can retrieve a signature for an image that no longer exists.

This asymmetry has a security-relevant consequence: deleting an image does not delete the signatures that vouch for it, and deleting a signature does not delete the image. An organisation that revokes an image by deleting its manifest has removed the bytes from the tag namespace but not from the digest namespace, and anyone holding the digest can still pull the blobs until garbage collection runs. Conversely, an attacker with push access to a repository can delete referrers, causing verification to fail, which is a denial rather than a forgery, but a denial that blocks deployment.

The practical rule is that the referrers index is a discovery mechanism, not an authority. It tells a verifier where to look. What the verifier finds there must be checked on its own terms: signature over payload, payload digest equal to the deployed digest, builder identity in the trusted set. What an Image Signature Covers and What It Leaves Out sets out those checks, and Provenance Statements and the Subject Digest covers the ones specific to attestations.

Where all of this is enforced (at the point of admission, before a workload is scheduled) is a separate design problem with its own failure modes. Admission-Time Verification and Digest Pinning takes the artifacts discovered here and asks what a cluster should do with them when a pod is created.

References

  1. OCI Distribution Specification — Referrers — Open Container Initiative
  2. OCI Image Spec — Artifact Manifest — Open Container Initiative
  3. SPDX Specification — Linux Foundation
  4. CycloneDX Specification — OWASP Foundation