From 2b67132e6c9c5c86d1698dbd472d3a28c89873c5 Mon Sep 17 00:00:00 2001 From: Sergey Sannikov Date: Mon, 13 Jul 2026 19:27:33 +0400 Subject: [PATCH] Raise DockerException for invalid ports in parse_host() parse_host() read the port via parsed_url.port, whose urllib property raises ValueError for out-of-range or non-numeric ports. That error escaped unwrapped, so a bad DOCKER_HOST surfaced as a raw ValueError instead of the DockerException the rest of parse_host() (and the invalid_hosts test contract) guarantees. Additionally, 'parsed_url.port or 0' collapsed an explicit ':0' into the no-port case. For ssh that appended ':22' to a netloc that already ended in ':0', producing a malformed 'ssh://host:0:22'; tcp://host:0 was already rejected, so the two protocols were inconsistent. Wrap the port access, distinguish a missing port (None) from an explicitly invalid one, and reject port 0 for both protocols. Signed-off-by: Sergey Sannikov --- docker/utils/utils.py | 13 +++++++++++-- tests/unit/utils_test.py | 4 ++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/docker/utils/utils.py b/docker/utils/utils.py index f36a3afb89..72d308f00d 100644 --- a/docker/utils/utils.py +++ b/docker/utils/utils.py @@ -290,14 +290,23 @@ def parse_host(addr, is_win32=False, tls=False): netloc = parsed_url.netloc if proto in ('tcp', 'ssh'): - port = parsed_url.port or 0 - if port <= 0: + try: + port = parsed_url.port + except ValueError as e: + raise errors.DockerException( + f'Invalid bind address format: {addr}' + ) from e + if port is None: if proto != 'ssh': raise errors.DockerException( f'Invalid bind address format: port is required: {addr}' ) port = 22 netloc = f'{parsed_url.netloc}:{port}' + elif port <= 0: + raise errors.DockerException( + f'Invalid bind address format: port is required: {addr}' + ) if not parsed_url.hostname: netloc = f'{DEFAULT_HTTP_HOST}:{port}' diff --git a/tests/unit/utils_test.py b/tests/unit/utils_test.py index 21da0b58e8..fccc2e10cc 100644 --- a/tests/unit/utils_test.py +++ b/tests/unit/utils_test.py @@ -285,6 +285,10 @@ def test_parse_host(self): 'unix:///sock/path#fragment', 'https://netloc:3333/path;params', 'ssh://:clearpassword@host:22', + 'tcp://host:0', + 'ssh://host:0', + 'tcp://host:99999', + 'tcp://host:notaport', ] valid_hosts = {