Skip to content

question: Clarify the semantics of image references with both tag and digest #2287

@andreas-mucha

Description

@andreas-mucha

Are image references in the format repo:tag@digest officially supported by the go-containerregistry library, and if so, is it guaranteed that its semantics are that the tag is functionally ignored and the digest is always evaluated?

Specifying image references with both tag and digest has become somewhat commonplace to combine readability for humans with the security benefits of digest pinning. The implicit consensus seems to be that the tag in this case is to be treated as informational ("I chose the image with this tag, which at the time of writing hat this digest"), while the digest is actually evaluated by the tooling.

However, there seems to be (generally, not only in this project) almost no documentation saying that this format is actually valid. AFAIK only Kubernetes officially states in their docs that this format is valid and works as described above.

In the go-containerregistry library, accepting the format as valid was introduced a long time ago (#391), and there are quite a few issue discussions about the topic and how the format should behave (e.g. #540, #702, #2069)

On the other hand, the name documentation states:

Image references [...] can end with a :tag or a @digest

Where I would interpret the "or" as exclusive.

Going into the code, ParseReference first tries parsing a Tag, and only failing that, a Digest:

func ParseReference(s string, opts ...Option) (Reference, error) {
if t, err := NewTag(s, opts...); err == nil {
return t, nil
}
if d, err := NewDigest(s, opts...); err == nil {
return d, nil
}
return nil, newErrBadName("could not parse reference: %s", s)
}

In NewTag, the tag is assumed to be the part after the last colon, so in image:tag@sha256:abcd it actually extracts the digest value abcd, and everything before that colon (image:tag@sha256) is passed to NewRepository. This then fails because of invalid characters (: and @). Only then NewDigest is called. So here the precedence of the digest over the tag kind of looks like a mere side effect of an implementation detail and not really intentional.

Going into the tests to determine intent is not really conclusive either: While digest_test.go explicitly tests the repo:tag@digest format as valid, tag_test.go does not conversely test it as invalid. Also ref_test.go contains no tests for the format.

So I would really appreciate if there could be some kind of clarification, ideally in the form of an documentation update, that image references with both tag and digest are allowed and how they are interpreted. Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions