Backported from distribution/distribution upstream: https://github.com/distribution/distribution/commit/521ea3d973cb0c7089ebbcdd4ccadc34be941f54 Modified to apply to vendored code by: corvus-callidus <108946721+corvus-callidus@users.noreply.github.com> - Adjusted paths - Removed references to files which are not present in the vendored code From 521ea3d973cb0c7089ebbcdd4ccadc34be941f54 Mon Sep 17 00:00:00 2001 From: "Jose D. Gomez R" Date: Mon, 24 Apr 2023 18:52:27 +0200 Subject: [PATCH] Fix runaway allocation on /v2/_catalog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduced a Catalog entry in the configuration struct. With it, it's possible to control the maximum amount of entries returned by /v2/catalog (`GetCatalog` in registry/handlers/catalog.go). It's set to a default value of 1000. `GetCatalog` returns 100 entries by default if no `n` is provided. When provided it will be validated to be between `0` and `MaxEntries` defined in Configuration. When `n` is outside the aforementioned boundary, ErrorCodePaginationNumberInvalid is returned. `GetCatalog` now handles `n=0` gracefully with an empty response as well. Signed-off-by: José D. Gómez R. <1josegomezr@gmail.com> Co-authored-by: Cory Snider --- vendor/github.com/docker/distribution/registry/api/v2/descriptors.go | 17 ++ vendor/github.com/docker/distribution/registry/api/v2/errors.go | 9 + 2 files changed, 26 insertions(+) diff --git a/vendor/github.com/docker/distribution/registry/api/v2/descriptors.go b/vendor/github.com/docker/distribution/registry/api/v2/descriptors.go index a9616c58ad..c3bf90f71d 100644 --- a/vendor/github.com/docker/distribution/registry/api/v2/descriptors.go +++ b/vendor/github.com/docker/distribution/registry/api/v2/descriptors.go @@ -134,6 +134,19 @@ var ( }, } + invalidPaginationResponseDescriptor = ResponseDescriptor{ + Name: "Invalid pagination number", + Description: "The received parameter n was invalid in some way, as described by the error code. The client should resolve the issue and retry the request.", + StatusCode: http.StatusBadRequest, + Body: BodyDescriptor{ + ContentType: "application/json", + Format: errorsBody, + }, + ErrorCodes: []errcode.ErrorCode{ + ErrorCodePaginationNumberInvalid, + }, + } + repositoryNotFoundResponseDescriptor = ResponseDescriptor{ Name: "No Such Repository Error", StatusCode: http.StatusNotFound, @@ -490,6 +503,7 @@ var routeDescriptors = []RouteDescriptor{ }, }, Failures: []ResponseDescriptor{ + invalidPaginationResponseDescriptor, unauthorizedResponseDescriptor, repositoryNotFoundResponseDescriptor, deniedResponseDescriptor, @@ -1578,6 +1592,9 @@ var routeDescriptors = []RouteDescriptor{ }, }, }, + Failures: []ResponseDescriptor{ + invalidPaginationResponseDescriptor, + }, }, }, }, diff --git a/vendor/github.com/docker/distribution/registry/api/v2/errors.go b/vendor/github.com/docker/distribution/registry/api/v2/errors.go index 97d6923aa0..87e9f3c14b 100644 --- a/vendor/github.com/docker/distribution/registry/api/v2/errors.go +++ b/vendor/github.com/docker/distribution/registry/api/v2/errors.go @@ -133,4 +133,13 @@ var ( longer proceed.`, HTTPStatusCode: http.StatusNotFound, }) + + ErrorCodePaginationNumberInvalid = errcode.Register(errGroup, errcode.ErrorDescriptor{ + Value: "PAGINATION_NUMBER_INVALID", + Message: "invalid number of results requested", + Description: `Returned when the "n" parameter (number of results + to return) is not an integer, "n" is negative or "n" is bigger than + the maximum allowed.`, + HTTPStatusCode: http.StatusBadRequest, + }) )