Skip to content

Commit 3d45036

Browse files
committed
validate pagination link host in container registry client
1 parent 5505e1d commit 3d45036

3 files changed

Lines changed: 27 additions & 0 deletions

File tree

sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
_compute_digest,
4242
_is_tag,
4343
_parse_next_link,
44+
_validate_next_link,
4445
_validate_digest,
4546
_get_blob_size,
4647
_get_manifest_size,
@@ -221,6 +222,7 @@ def prepare_request(next_link=None):
221222
url, query_parameters, header_parameters
222223
)
223224
else:
225+
_validate_next_link(next_link, self._endpoint)
224226
url = next_link
225227
query_parameters: Dict[str, Any] = {}
226228
path_format_arguments = {
@@ -369,6 +371,7 @@ def prepare_request(next_link=None):
369371
url, query_parameters, header_parameters
370372
)
371373
else:
374+
_validate_next_link(next_link, self._endpoint)
372375
url = next_link
373376
query_parameters: Dict[str, Any] = {}
374377
path_format_arguments = {
@@ -598,6 +601,7 @@ def prepare_request(next_link=None):
598601
url, query_parameters, header_parameters
599602
)
600603
else:
604+
_validate_next_link(next_link, self._endpoint)
601605
url = next_link
602606
query_parameters: Dict[str, Any] = {}
603607
path_format_arguments = {

sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,25 @@ def _parse_next_link(link_string: str) -> Optional[str]:
104104
return link_string[1 : link_string.find(">")]
105105

106106

107+
def _validate_next_link(next_link: str, endpoint: str) -> None:
108+
"""Ensure a pagination continuation link targets the configured registry host.
109+
110+
The continuation link comes from a service response (the Link header or the
111+
response body) and is therefore untrusted. A relative link, or an absolute
112+
link whose host matches the endpoint, is accepted. An absolute link to any
113+
other host is rejected so request credentials are never sent to a host the
114+
caller did not configure.
115+
116+
:param str next_link: The continuation link returned by the service.
117+
:param str endpoint: The configured registry endpoint.
118+
:return: None
119+
:raises ValueError: If next_link points at a different host than endpoint.
120+
"""
121+
host = urlparse(next_link).netloc
122+
if host and host.lower() != urlparse(endpoint).netloc.lower():
123+
raise ValueError("The continuation link host does not match the registry endpoint.")
124+
125+
107126
def _enforce_https(request: PipelineRequest) -> None:
108127
"""Raise ServiceRequestError if the request URL is non-HTTPS and the sender did not specify enforce_https=False
109128

sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
_compute_digest,
5151
_is_tag,
5252
_parse_next_link,
53+
_validate_next_link,
5354
_validate_digest,
5455
_get_blob_size,
5556
_get_manifest_size,
@@ -223,6 +224,7 @@ def prepare_request(next_link=None):
223224

224225
else:
225226
# make call to next link with the client's api-version
227+
_validate_next_link(next_link, self._endpoint)
226228
_parsed_next_link = urllib.parse.urlparse(next_link)
227229
_next_request_params = case_insensitive_dict(
228230
{
@@ -365,6 +367,7 @@ def prepare_request(next_link=None):
365367
_request.url, **path_format_arguments
366368
) # pylint: disable=protected-access
367369
else:
370+
_validate_next_link(next_link, self._endpoint)
368371
_parsed_next_link = urllib.parse.urlparse(next_link)
369372
_next_request_params = case_insensitive_dict(
370373
{
@@ -608,6 +611,7 @@ def prepare_request(next_link=None):
608611
url, query_parameters, header_parameters
609612
)
610613
else:
614+
_validate_next_link(next_link, self._endpoint)
611615
url = next_link
612616
query_parameters: Dict[str, Any] = {}
613617
path_format_arguments = {

0 commit comments

Comments
 (0)