description
find_entries_for_url in src/specify_cli/authentication/config.py does (urlparse(url).hostname or "").lower() unguarded. a malformed authority (e.g. an unterminated ipv6 bracket https://[::1, or a bracketed non-ip host https://[not-an-ip]) makes urlparse/hostname raise ValueError, so instead of the empty list the function already returns for a host-less url, a raw ValueError escapes.
this function is the first step of the shared http client - build_request and open_url both call it before any url validation - so the raw error can leak out of catalog/extension/preset fetches.
repro:
from specify_cli.authentication.config import find_entries_for_url
find_entries_for_url("https://[::1", []) # ValueError: Invalid IPv6 URL
expected: no matches ([]), same as the host-less url case just above it.
same bug class as #3210 / the recent bundler + catalog validator fixes.
note: i used an ai assistant to help investigate and write this up.
description
find_entries_for_urlinsrc/specify_cli/authentication/config.pydoes(urlparse(url).hostname or "").lower()unguarded. a malformed authority (e.g. an unterminated ipv6 brackethttps://[::1, or a bracketed non-ip hosthttps://[not-an-ip]) makes urlparse/hostname raiseValueError, so instead of the empty list the function already returns for a host-less url, a rawValueErrorescapes.this function is the first step of the shared http client -
build_requestandopen_urlboth call it before any url validation - so the raw error can leak out of catalog/extension/preset fetches.repro:
expected: no matches (
[]), same as the host-less url case just above it.same bug class as #3210 / the recent bundler + catalog validator fixes.
note: i used an ai assistant to help investigate and write this up.