Repository: containerd/containerd
File: core/remotes/docker/referrers.go (Go)

Code before:
import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strings"

	"github.com/containerd/errdefs"
	"github.com/containerd/log"
	digest "github.com/opencontainers/go-digest"
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)

func (r dockerFetcher) FetchReferrers(ctx context.Context, dgst digest.Digest, artifactTypes ...string) ([]ocispec.Descriptor, error) {
	rc, size, err := r.openReferrers(ctx, dgst, artifactTypes...)
	if err != nil {
		return nil, err
	}
	defer rc.Close()

	var index ocispec.Index
	if err := json.NewDecoder(io.LimitReader(rc, size)).Decode(&index); err != nil {
		return nil, fmt.Errorf("failed to decode referrers index: %w", err)
	}
	return index.Manifests, nil
}

func (r dockerFetcher) openReferrers(ctx context.Context, dgst digest.Digest, artifactTypes ...string) (io.ReadCloser, int64, error) {
	mediaType := ocispec.MediaTypeImageIndex
	ctx = log.WithLogger(ctx, log.G(ctx).WithField("digest", dgst))

	hosts := r.filterHosts(HostCapabilityReferrers)
	fallbackHosts := r.filterHosts(HostCapabilityResolve)
	if len(hosts) == 0 && len(fallbackHosts) == 0 {
		return nil, 0, fmt.Errorf("no pull hosts: %w", errdefs.ErrNotFound)
	}

	ctx, err := ContextWithRepositoryScope(ctx, r.refspec, false)
	if err != nil {
		return nil, 0, err
	}

	for i, host := range hosts {
		req := r.request(host, http.MethodGet, "referrers", dgst.String())
		for _, artifactType := range artifactTypes {
			if err := req.addQuery("artifactType", artifactType); err != nil {
				return nil, 0, err
			}
		}
		if err := req.addNamespace(r.refspec.Hostname()); err != nil {

Review comment (suggestion):
As matching the artifactType is not guaranteed, then this should reapply the filter manually before returning.

Code after:
import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"strings"

	"github.com/containerd/errdefs"
	"github.com/containerd/log"
	digest "github.com/opencontainers/go-digest"
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)

func (r dockerFetcher) FetchReferrers(ctx context.Context, dgst digest.Digest, artifactTypes ...string) ([]ocispec.Descriptor, error) {
	rc, size, err := r.openReferrers(ctx, dgst, artifactTypes...)
	if err != nil {
		return nil, err
	}
	defer rc.Close()

	var index ocispec.Index
	dec := json.NewDecoder(io.LimitReader(rc, size))
	if err := dec.Decode(&index); err != nil {
		return nil, fmt.Errorf("failed to decode referrers index: %w", err)
	}
	if _, err := dec.Token(); !errors.Is(err, io.EOF) {
		return nil, fmt.Errorf("unexpected data after JSON object")
	}

	if len(artifactTypes) == 0 {
		return index.Manifests, nil
	}

	var referrers []ocispec.Descriptor
	tFilter := map[string]struct{}{}
	for _, t := range artifactTypes {
		tFilter[t] = struct{}{}
	}
	for _, desc := range index.Manifests {
		if _, ok := tFilter[desc.ArtifactType]; ok {
			referrers = append(referrers, desc)
		}
	}
	return referrers, nil
}

func (r dockerFetcher) openReferrers(ctx context.Context, dgst digest.Digest, artifactTypes ...string) (io.ReadCloser, int64, error) {
	mediaType := ocispec.MediaTypeImageIndex
	ctx = log.WithLogger(ctx, log.G(ctx).WithField("digest", dgst))