Follow OCI distribution spec for artifactType and annotations by malt3 · Pull Request #2269 · google/go-containerregistry (original) (raw)

added 2 commits

April 20, 2026 11:27

@malt3

Per the OCI distribution spec (distribution-spec#395), the artifactType on a descriptor should be set to the manifest's artifactType if present, falling back to config.mediaType unconditionally (not only for non-standard config types as was done previously). Additionally, annotations from the manifest are now copied to the descriptor.

Current wording from the spec:

Pushing Manifests with Subject

When processing a request for an image manifest with the subject field, a registry implementation that supports the referrers API MUST respond with the response header OCI-Subject: to indicate to the client that the registry processed the request's subject.

When pushing a manifest with the subject field and the OCI-Subject header was not set, the client MUST:

  1. Pull the current referrers list using the referrers tag schema.
  2. If that pull returns a manifest other than the expected image index, the client SHOULD report a failure and skip the remaining steps.
  3. If the tag returns a 404, the client MUST begin with an empty image index.
  4. Verify the descriptor for the manifest is not already in the referrers list (duplicate entries SHOULD NOT be created).
  5. Append a descriptor for the pushed manifest to the manifests in the referrers list. The value of the artifactType MUST be set to the artifactType value in the pushed manifest, if present. If the artifactType is empty or missing in a pushed image manifest, the value of artifactType MUST be set to the config descriptor mediaType value. All annotations from the pushed manifest MUST be copied to this descriptor.
  6. Push the updated referrers list using the same referrers tag schema. The client MAY use conditional HTTP requests to prevent overwriting a referrers list that has changed since it was first pulled.

With this change, we correctly follow step 5.

Changes:

@malt3

Test the OCI distribution spec behavior for artifactType resolution and annotation copying:

Subserial

This was referenced

Apr 20, 2026

@malt3 malt3 deleted the referrers-api-use-correct-artifact-type branch

April 20, 2026 23:06

Subserial pushed a commit to Subserial/go-containerregistry that referenced this pull request

May 15, 2026

@malt3 @Subserial

…#2269)

Per the OCI distribution spec (distribution-spec#395), the artifactType on a descriptor should be set to the manifest's artifactType if present, falling back to config.mediaType unconditionally (not only for non-standard config types as was done previously). Additionally, annotations from the manifest are now copied to the descriptor.

Current wording from the spec:

Pushing Manifests with Subject

When processing a request for an image manifest with the subject field, a registry implementation that supports the referrers API MUST respond with the response header OCI-Subject: to indicate to the client that the registry processed the request's subject.

When pushing a manifest with the subject field and the OCI-Subject header was not set, the client MUST:

  1. Pull the current referrers list using the referrers tag schema.
  2. If that pull returns a manifest other than the expected image index, the client SHOULD report a failure and skip the remaining steps.
  3. If the tag returns a 404, the client MUST begin with an empty image index.
  4. Verify the descriptor for the manifest is not already in the referrers list (duplicate entries SHOULD NOT be created).
  5. Append a descriptor for the pushed manifest to the manifests in the referrers list. The value of the artifactType MUST be set to the artifactType value in the pushed manifest, if present. If the artifactType is empty or missing in a pushed image manifest, the value of artifactType MUST be set to the config descriptor mediaType value. All annotations from the pushed manifest MUST be copied to this descriptor.
  6. Push the updated referrers list using the same referrers tag schema. The client MAY use conditional HTTP requests to prevent overwriting a referrers list that has changed since it was first pulled.

With this change, we correctly follow step 5.

Changes:

Test the OCI distribution spec behavior for artifactType resolution and annotation copying:

This was referenced

May 19, 2026

jimmidyson added a commit to mesosphere/mindthegap that referenced this pull request

May 19, 2026

@jimmidyson

Bump google/go-containerregistry from v0.21.5 to v0.21.6 to include google/go-containerregistry#2302 (transport: allow bearer realm at same host:port as registry).

The realm-URL validation introduced in go-containerregistry#2243 (shipped in v0.21.5) rejects realms whose host resolves to a private, loopback, or link-local IP. This is the right default for the cross-host SSRF case (a malicious registry pointing the token endpoint at 169.254.169.254 or a sister internal service), but it breaks mindthegap push bundle (and downstream nkp push bundle) against on-prem registries that colocate the registry and bearer- token endpoint on the same private IP. e.g. for an internal Harbor at https://10.162.182.23:5000/library the push aborts with:

invalid realm in www-authenticate: realm host
"10.162.182.23" is a private or link-local address

v0.21.6 keeps the cross-host SSRF block but adds a same-host:port exception: when the realm URL host AND port match the registry, the private-IP check is skipped. The realm cannot escape a trust boundary the user already crossed by passing the registry reference.

The transitive bumps (docker/cli, moby/moby, docker/go-connections, klauspost/compress, golang.org/x/{crypto,mod,net,sys,term,text, tools}) are pulled in by go-containerregistry v0.21.6 go.mod via MVS resolution. The containerd/stargz-snapshotter/estargz and vbatts/tar-split indirect dependencies are dropped because v0.21.6 removed estargz support (go-containerregistry#2288).

Test expectations in images/manifest_test.go are updated for the unrelated OCI-spec compliance change in google/go-containerregistry#2269: mutate.AppendManifests now sets the index entry ArtifactType to the image Config.MediaType when the image manifest does not itself set artifactType. For the Docker schema2 fixture in TestManifestListForImage_RemoteImage this becomes "application/vnd.docker.container.image.v1+json" (types.DockerConfigJSON).

jimmidyson added a commit to mesosphere/mindthegap that referenced this pull request

May 19, 2026

@jimmidyson

…223) (#1046)

Summary

Background

The realm-URL validation introduced in go-containerregistry#2243 (shipped in v0.21.5) rejects realms whose host resolves to a private, loopback, or link-local IP. This is the right default for the cross-host SSRF case (a malicious registry pointing the token endpoint at 169.254.169.254 or a sister internal service), but it broke legitimate on-prem deployments that serve their own token endpoint at the same host:port as the registry. #2258 tracked the discussion; #2302 implements the agreed fix: keep the cross-host SSRF block, but skip the private-IP check when the realm URL host AND port match the registry host:port.

Transitive dependency changes

Pulled in by go-containerregistry v0.21.6's go.mod via MVS resolution:

Dropped (v0.21.6 removed estargz support in go-containerregistry#2288):

Test fixture update

images/manifest_test.go is updated for the unrelated OCI-spec compliance change in go-containerregistry#2269: mutate.AppendManifests now sets the index entry ArtifactType to the image's Config.MediaType when the image manifest does not itself set artifactType. For the Docker schema2 fixture in TestManifestListForImage_RemoteImage this becomes "application/vnd.docker.container.image.v1+json" (types.DockerConfigJSON).

Test plan

Out of scope

The two pre-existing govulncheck stdlib findings (GO-2026-4982, GO-2026-4980, GO-2026-4971, GO-2026-4918 — all go1.25.x fixed in go1.25.10) are unrelated to this change.

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters

[ Show hidden characters]({{ revealButtonHref }})