fix(github-http): return None on malformed GHES port instead of raising (#3379)

resolve_github_release_asset_api_url's is_ghes branch built the authority
with 'parsed.port', which raises ValueError on a malformed port (e.g.
host:notaport). The function's contract is to resolve or return None,
never raise — every other unresolvable case returns None. An allowlisted
GHES host with a bad port therefore crashed the caller. Read parsed.port
defensively and return None on ValueError.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Ali jawwad
2026-07-08 01:14:25 +05:00
committed by GitHub
parent 10d4bca64c
commit a307894709
2 changed files with 25 additions and 1 deletions

View File

@@ -127,7 +127,14 @@ def resolve_github_release_asset_api_url(
if hostname == "github.com":
api_base = "https://api.github.com"
elif is_ghes:
authority = hostname if parsed.port is None else f"{hostname}:{parsed.port}"
# ``parsed.port`` raises ValueError on a malformed port (e.g.
# ``host:notaport``); the function's contract is to return None for
# anything it can't resolve, not to raise.
try:
port = parsed.port
except ValueError:
return None
authority = hostname if port is None else f"{hostname}:{port}"
api_base = f"{parsed.scheme}://{authority}/api/v3"
else:
return None

View File

@@ -233,6 +233,23 @@ class TestResolveGitHubReleaseAssetApiUrl:
assert result is None
assert called == []
def test_returns_none_on_malformed_ghes_port(self):
"""A malformed port on an allowlisted GHES host returns None, not a
ValueError (contract: resolve or return None, never raise)."""
called = []
def open_never(url, timeout=None, extra_headers=None):
called.append(url)
raise AssertionError("open_url_fn must not be called")
result = resolve_github_release_asset_api_url(
"https://ghes.example:notaport/o/r/releases/download/v1/ext.zip",
open_never,
github_hosts=("ghes.example",),
)
assert result is None
assert called == []
def test_passthrough_for_unlisted_ghes_api_asset_url(self):
"""A direct GHES /api/v3 asset URL passes through even when the host is
not allowlisted: passthrough issues no API request, and the download