Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ require (
golang.org/x/exp v0.0.0-20260611194520-c48552f49976 // indirect
golang.org/x/net v0.56.0 // indirect
golang.org/x/oauth2 v0.36.0 // indirect
golang.org/x/sync v0.21.0 // indirect
golang.org/x/sync v0.22.0 // indirect
golang.org/x/sys v0.46.0 // indirect
golang.org/x/term v0.44.0 // indirect
golang.org/x/text v0.38.0 // indirect
Expand All @@ -205,7 +205,7 @@ require (
k8s.io/metrics v0.36.2 // indirect
k8s.io/streaming v0.36.2 // indirect
k8s.io/utils v0.0.0-20260617174310-a95e086a2553 // indirect
oras.land/oras-go/v2 v2.6.1 // indirect
oras.land/oras-go/v2 v2.6.2 // indirect
sigs.k8s.io/controller-runtime v0.24.1 // indirect
sigs.k8s.io/gateway-api v1.6.0 // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -556,8 +556,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down Expand Up @@ -662,8 +662,8 @@ k8s.io/streaming v0.36.2 h1:NSKthPPg9UFSKsRauVJUVGH2Dvn8fhKmY4qrMkw/p98=
k8s.io/streaming v0.36.2/go.mod h1:z6fV3D+NVkoeqRMtWwlUZK6U17SY/LqNzOxWL6GyR/s=
k8s.io/utils v0.0.0-20260617174310-a95e086a2553 h1:hmGqDecjc8d7HVzWzRFl0QD9bYuYKbBEG7t8xwnVxfI=
k8s.io/utils v0.0.0-20260617174310-a95e086a2553/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
oras.land/oras-go/v2 v2.6.1 h1:bonOEkjLfp8tt6qXWRRWP6p1F+9octchOf2EqnWB4Zs=
oras.land/oras-go/v2 v2.6.1/go.mod h1:dhtFrFOuZuDtAVeZ9FUnaa5zfzplG3ZnFX9/uH1J/Yk=
oras.land/oras-go/v2 v2.6.2 h1:N04RXngAp1LJKTG6ifz3xHPipasEkWr+hFmInja5YKo=
oras.land/oras-go/v2 v2.6.2/go.mod h1:PlTtg4JTDJkDe8yVHpM2wz7/YDc00GVas+i4jAW2TZ4=
sigs.k8s.io/controller-runtime v0.24.1 h1:miPEwrmirImAvgME1L9qebGHrOnGJoVmVdtOU9fRfo4=
sigs.k8s.io/controller-runtime v0.24.1/go.mod h1:vFkfY5fGt5xAC/sKb8IBFKgWPNKG9OUG29dR8Y2wImw=
sigs.k8s.io/gateway-api v1.6.0 h1:735YBRj5NXFrOGX0GoSjwzUIzbz8kiEOfADsqHFmHgE=
Expand Down
17 changes: 13 additions & 4 deletions vendor/golang.org/x/sync/semaphore/semaphore.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1311,7 +1311,7 @@ golang.org/x/net/websocket
## explicit; go 1.25.0
golang.org/x/oauth2
golang.org/x/oauth2/internal
# golang.org/x/sync v0.21.0
# golang.org/x/sync v0.22.0
## explicit; go 1.25.0
golang.org/x/sync/errgroup
golang.org/x/sync/semaphore
Expand Down Expand Up @@ -1968,7 +1968,7 @@ k8s.io/utils/internal/third_party/forked/golang/net
k8s.io/utils/net
k8s.io/utils/ptr
k8s.io/utils/trace
# oras.land/oras-go/v2 v2.6.1
# oras.land/oras-go/v2 v2.6.2
## explicit; go 1.25.0
oras.land/oras-go/v2
oras.land/oras-go/v2/content
Expand Down
35 changes: 25 additions & 10 deletions vendor/oras.land/oras-go/v2/content/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ limitations under the License.
package content

import (
"bytes"
"errors"
"fmt"
"io"
Expand All @@ -24,11 +25,15 @@ import (
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)

// maxDescriptorSize is the upper-bound for descriptor sizes accepted by
// ReadAll. Descriptors sourced from attacker-supplied OCI layouts can carry
// arbitrarily large Size values; without this cap, make([]byte, desc.Size)
// triggers a runtime panic before any allocation occurs.
const maxDescriptorSize = 32 * 1024 * 1024 // 32 MiB
// maxInitialBufferSize bounds the buffer that ReadAll pre-allocates from
// desc.Size before any content is read. desc.Size is attacker-controllable: a
// crafted OCI layout index.json can declare an arbitrarily large Size (e.g.
// 2^62), and make([]byte, desc.Size) on such a value triggers a runtime panic
// ("makeslice: len out of range") before any allocation occurs. ReadAll caps
// the initial allocation at this value and grows the buffer as it reads, so the
// declared size is never trusted for allocation while legitimately large
// content (e.g. plugin or chart layers) is still read in full.
const maxInitialBufferSize = 32 * 1024 * 1024 // 32 MiB

var (
// ErrInvalidDescriptorSize is returned by ReadAll() when
Expand Down Expand Up @@ -125,22 +130,32 @@ func NewVerifyReader(r io.Reader, desc ocispec.Descriptor) *VerifyReader {
// The read content is verified against the size and the digest
// using a VerifyReader.
func ReadAll(r io.Reader, desc ocispec.Descriptor) ([]byte, error) {
if desc.Size < 0 || desc.Size > maxDescriptorSize {
if desc.Size < 0 {
return nil, ErrInvalidDescriptorSize
}
buf := make([]byte, desc.Size)

vr := NewVerifyReader(r, desc)
if n, err := io.ReadFull(vr, buf); err != nil {

// Do not pre-allocate desc.Size directly: it is attacker-controllable and a
// forged value (e.g. 2^62) would panic make(). Cap the initial allocation
// and let the buffer grow as content is read. The VerifyReader enforces the
// declared size and digest, so a size that does not match the actual content
// still fails verification rather than over-allocating.
initialCap := desc.Size
if initialCap > maxInitialBufferSize {
initialCap = maxInitialBufferSize
}
buf := bytes.NewBuffer(make([]byte, 0, initialCap))
if _, err := buf.ReadFrom(vr); err != nil {
if errors.Is(err, io.ErrUnexpectedEOF) {
return nil, fmt.Errorf("read failed: expected content size of %d, got %d, for digest %s: %w", desc.Size, n, desc.Digest.String(), err)
return nil, fmt.Errorf("read failed: expected content size of %d, got %d, for digest %s: %w", desc.Size, buf.Len(), desc.Digest.String(), err)
}
return nil, fmt.Errorf("read failed: %w", err)
}
if err := vr.Verify(); err != nil {
return nil, err
}
return buf, nil
return buf.Bytes(), nil
}

// ensureEOF ensures the read operation ends with an EOF and no
Expand Down
1 change: 1 addition & 0 deletions vendor/oras.land/oras-go/v2/errdef/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ var (
ErrMissingReference = errors.New("missing reference")
ErrNotFound = errors.New("not found")
ErrSizeExceedsLimit = errors.New("size exceeds limit")
ErrTooManyPages = errors.New("too many pages")
ErrUnsupported = errors.New("unsupported")
ErrUnsupportedVersion = errors.New("unsupported version")
)
24 changes: 22 additions & 2 deletions vendor/oras.land/oras-go/v2/registry/remote/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,18 @@ type Repository struct {
// Reference: https://github.com/oras-project/oras-go/issues/841
ReferrerListPageSize int

// TagListMaxPages limits the total number of pages fetched during tag
// listing, bounding server-driven pagination so a malicious or misbehaving
// registry cannot force unbounded requests.
// If zero, tag listing is unlimited.
TagListMaxPages int

// ReferrerListMaxPages limits the total number of pages fetched during
// referrer listing, bounding server-driven pagination so a malicious or
// misbehaving registry cannot force unbounded requests.
// If zero, referrer listing is unlimited.
ReferrerListMaxPages int

// MaxMetadataBytes specifies a limit on how many response bytes are allowed
// in the server's response to the metadata APIs, such as catalog list, tag
// list, and referrers list.
Expand Down Expand Up @@ -205,6 +217,8 @@ func (r *Repository) clone() *Repository {
ManifestMediaTypes: slices.Clone(r.ManifestMediaTypes),
TagListPageSize: r.TagListPageSize,
ReferrerListPageSize: r.ReferrerListPageSize,
TagListMaxPages: r.TagListMaxPages,
ReferrerListMaxPages: r.ReferrerListMaxPages,
MaxMetadataBytes: r.MaxMetadataBytes,
SkipReferrersGC: r.SkipReferrersGC,
HandleWarning: r.HandleWarning,
Expand Down Expand Up @@ -400,7 +414,10 @@ func (r *Repository) Tags(ctx context.Context, last string, fn func(tags []strin
ctx = auth.AppendRepositoryScope(ctx, r.Reference, auth.ActionPull)
url := buildRepositoryTagListURL(r.PlainHTTP, r.Reference)
var err error
for err == nil {
for page := 0; err == nil; page++ {
if r.TagListMaxPages > 0 && page >= r.TagListMaxPages {
return fmt.Errorf("tag listing exceeded %d pages: %w", r.TagListMaxPages, errdef.ErrTooManyPages)
}
url, err = r.tags(ctx, last, fn, url)
// clear `last` for subsequent pages
last = ""
Expand Down Expand Up @@ -512,7 +529,10 @@ func (r *Repository) referrersByAPI(ctx context.Context, desc ocispec.Descriptor

url := buildReferrersURL(r.PlainHTTP, ref, artifactType)
var err error
for err == nil {
for page := 0; err == nil; page++ {
if r.ReferrerListMaxPages > 0 && page >= r.ReferrerListMaxPages {
return fmt.Errorf("referrer listing exceeded %d pages: %w", r.ReferrerListMaxPages, errdef.ErrTooManyPages)
}
url, err = r.referrersPageByAPI(ctx, artifactType, fn, url)
}
if err == errNoLink {
Expand Down
32 changes: 32 additions & 0 deletions vendor/oras.land/oras-go/v2/registry/remote/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"fmt"
"io"
"net/http"
"net/url"
"strings"

ocispec "github.com/opencontainers/image-spec/specs-go/v1"
Expand Down Expand Up @@ -55,9 +56,40 @@ func parseLink(resp *http.Response) (string, error) {
if err != nil {
return "", err
}
// The Link header value is controlled by the (potentially malicious)
// registry. Restrict pagination to the same origin as the originating
// request so that a registry cannot redirect pagination to an arbitrary
// host and turn a listing call into a server-side request forgery.
if !isSameOrigin(resp.Request.URL, linkURL) {
return "", fmt.Errorf("invalid next link %q: not the same origin as %q", link, resp.Request.URL)
}
return linkURL.String(), nil
}

// isSameOrigin reports whether the two URLs share the same origin, that is the
// same scheme, host, and port (with the default port applied for http/https).
func isSameOrigin(a, b *url.URL) bool {
if !strings.EqualFold(a.Scheme, b.Scheme) {
return false
}
return canonicalHostPort(a) == canonicalHostPort(b)
}

// canonicalHostPort returns the lower-cased "host:port" of u, filling in the
// default port for the http and https schemes when none is present.
func canonicalHostPort(u *url.URL) string {
port := u.Port()
if port == "" {
switch strings.ToLower(u.Scheme) {
case "https":
port = "443"
case "http":
port = "80"
}
}
return strings.ToLower(u.Hostname()) + ":" + port
}

// limitReader returns a Reader that reads from r but stops with EOF after n
// bytes. If n is less than or equal to zero, defaultMaxMetadataBytes is used.
func limitReader(r io.Reader, n int64) io.Reader {
Expand Down
Loading