skip to content

If any authenticated user can push a referrer to an image digest, what does signature discovery prove?

level: middleimportance: nice to knowfreq 28%

answer

  1. a lookup is not an authentication
  2. the index is writable input
  3. who may speak about a digest is unenforced
  4. entries are candidates, not evidence
  5. counting entries counts pushes

basics

~20 s

Only that someone with push access to that repository put an object there. Discovery is a lookup, not authentication: the referrers index is attacker-writable input, and trust comes from validating a signature and its signer identity, never from presence.

solid answer

~50 s

Discovery answers "what claims to be about this digest", which is a much weaker statement than "this digest is signed by someone I accept". On a shared registry, anyone who can push into a repository can push a manifest whose `subject` is any digest they like, including one they do not own — the registry indexes the back-edge without any notion of who is entitled to vouch for what. So the referrers index is untrusted input. Everything it returns is a *candidate*: fetch it, verify the signature cryptographically over the subject digest, and then check that the identity behind it is one your policy names. A policy of "at least one referrer of type signature exists" is defeated by a single push. So is counting — ten referrers is not a quorum, it is ten pushes. The correct shape is: require at least one candidate that verifies and matches an accepted identity, and ignore everything else rather than failing on it.

go deeper

for a junior

Take away the rule: finding a signature is not the same as checking one, and a check that stops at "something is attached" is not a security control.

for a middle

Explain why the referrers index is writable by anyone with push access to the repository, and what that makes of presence checks and entry counting.

for a senior

Describe a verifier that treats candidates as untrusted input — filter, validate, accept on first match, ignore non-matches, and bound the work so the index cannot stall admission.

for a principal

Frame it as trust-boundary placement: the registry is storage, not an authority, so the decision must sit in a verifier you control, and any threshold you promise auditors has to be over independent verified identities.

## Two questions people conflate - **Discovery:** given a digest, what objects in this repository refer to it? Answered by the registry, cheaply, with no cryptography involved. - **Verification:** is there a signature over this digest that validates, and does it come from a signer my policy accepts? Answered by the verifier, using the payloads discovery handed it. Discovery is a database query. It has exactly the trust properties of the registry's write path, which is to say: anything a principal with push access chose to put there. ## Why the index is attacker-writable The `subject` field is just a field. When a manifest carrying it is pushed, the registry records the back-edge so future referrers queries return it. Registries do not — and largely cannot — enforce that the pusher is entitled to speak about the subject digest: a signature attached later by a scanner, an approval added by a release manager, an SBOM published by a different team are all legitimate uses of exactly that ability. The permission model is per-repository write, not per-subject. In a multi-tenant registry, that means an authenticated low-privilege tenant with push rights into a shared repository can attach objects to a digest belonging to someone else's release. Nothing about the artifact changes; the artifact's digest is untouched and its real signatures are still there. What changes is the *candidate set* every verifier now walks. ## What that buys an attacker, and what it does not It does **not** let them forge trust: they cannot produce a signature that validates against an identity your policy accepts, because that is a cryptographic problem, not a registry-permissions one. The attacks are shaped differently: **Defeating presence checks.** Any policy of the form "proceed if a signature-typed referrer exists" is defeated by one push of a well-formed object with the right artifact type and a payload nobody validates. This is the single most common real-world weakness in home-grown verification, and it is why signing without verifying changes nothing. **Defeating counting.** "Require two signatures" implemented as "the index lists two entries" is the same bug wearing a suit. Two entries is two pushes. A threshold is only meaningful over *distinct verified identities*, and it has to be evaluated after validation, not before. **Poisoning the walk.** If the verifier treats a malformed or non-validating referrer as an error rather than as a non-match, a single junk entry can turn verification into a hard failure for a perfectly good artifact — a denial of the deploy path rather than a bypass of it. Flooding the index with many entries is the volumetric version of the same idea, adding fetch cost and latency to every admission decision. ## The correct verifier shape 1. Discover candidates for the digest, and filter by artifact type client-side rather than assuming a server-side filter was honoured. 2. For each candidate, fetch and validate: does the signature verify over *this* subject digest, and does the identity behind it match one the policy names? 3. Accept if at least one candidate passes. Ignore the rest — a non-matching referrer is data, not an incident. 4. Bound the work: cap how many candidates you will fetch, so the index cannot become a lever on your deploy path. Step 2's second half — which identities to accept — is a policy question with its own depth, and the honest short answer in an interview is that "a valid signature" is meaningless without "by whom": a signature that verifies against a key or identity you never intended to trust is exactly as worthless as no signature at all. ## The one-line version Discovery tells you where to look. It never tells you what to believe. Any control whose decision is reached before a cryptographic check has happened is a control an attacker can satisfy by pushing.

  • Does this mean the attacker can make a malicious image pass verification?
    No — not through this route. They cannot produce a signature that validates against an identity your policy accepts, since that is a cryptographic barrier and pushing into a repository does not cross it. What they can do is satisfy any check that stops at presence or count, and disrupt any verifier that treats a bad candidate as a fatal error rather than a non-match.
  • How should a verifier handle a referrer whose signature does not validate?
    Skip it and keep going. A non-validating candidate is a normal condition — a stale attachment, a different signer, an unrelated artifact type, or junk somebody pushed — and treating it as a hard failure hands anyone with push access a way to block deploys. Fail only when no candidate validates against an accepted identity, and log the rejected ones so the noise is visible.
  • Is requiring two signatures a meaningful control here?
    Only if the threshold is evaluated over distinct identities that each verified, after validation. Counting index entries counts pushes and is trivially satisfied. Even done correctly, two signatures from identities that share the same compromise path — the same build system, the same credential — is one signature with extra steps, so the useful question is what independence the second signer actually adds.

Anyone can staple a note to a public noticeboard saying they approved your release. The staple is real; the approval is only worth what the handwriting proves.

saying these in an interview costs you the question

  • Treats the existence of a referrer as proof the artifact is signed
  • Counts index entries to satisfy a multi-signature requirement
  • Fails the whole verification when one candidate does not validate
  • Assumes registries restrict who may refer to a given digest
  • Says a valid signature is enough without naming an accepted signer

context