mirror of
https://github.com/github/spec-kit.git
synced 2026-07-09 08:13:19 +08:00
fix(bundler): validate catalog URLs in catalog add (HTTPS-only, require host) (#3367)
* fix(bundler): validate catalog URLs in `catalog add` (HTTPS-only, require host) add_source persisted remote catalog URLs without the HTTPS/host checks that specify_cli.catalogs (#3210) and the bundler adapters (#3333) enforce, and an unclosed IPv6 bracket escaped as a raw ValueError. Mirror the catalogs.py validation for http(s) schemes and wrap urlparse so malformed input raises BundlerError. Fixes #3366 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: correct config filename and validation reference in comment Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -222,3 +222,39 @@ def test_add_source_allows_local_path_with_colon(tmp_path: Path, monkeypatch):
|
||||
# A relative path containing ':' but no '://' is still a local path.
|
||||
source = cc.add_source(project, "weird:name.json", policy="install-allowed", priority=50)
|
||||
assert source.url.endswith("weird:name.json") or "weird" in source.url
|
||||
|
||||
|
||||
def test_add_source_rejects_plain_http_for_non_localhost(tmp_path: Path):
|
||||
project = tmp_path / "proj"
|
||||
(project / ".specify").mkdir(parents=True)
|
||||
with pytest.raises(BundlerError, match="HTTPS"):
|
||||
cc.add_source(project, "http://example.com/catalog.json", policy="install-allowed", priority=50)
|
||||
|
||||
|
||||
def test_add_source_allows_http_for_localhost(tmp_path: Path):
|
||||
project = tmp_path / "proj"
|
||||
(project / ".specify").mkdir(parents=True)
|
||||
source = cc.add_source(project, "http://localhost:8080/c.json", policy="install-allowed", priority=50)
|
||||
assert source.url == "http://localhost:8080/c.json"
|
||||
|
||||
|
||||
def test_add_source_rejects_host_less_remote_urls(tmp_path: Path):
|
||||
project = tmp_path / "proj"
|
||||
(project / ".specify").mkdir(parents=True)
|
||||
for url in ("https://:8080", "https://user@"):
|
||||
with pytest.raises(BundlerError, match="host"):
|
||||
cc.add_source(project, url, policy="install-allowed", priority=50)
|
||||
|
||||
|
||||
def test_add_source_wraps_invalid_ipv6_as_bundler_error(tmp_path: Path):
|
||||
project = tmp_path / "proj"
|
||||
(project / ".specify").mkdir(parents=True)
|
||||
with pytest.raises(BundlerError, match="Invalid catalog url"):
|
||||
cc.add_source(project, "https://[::1/c.json", policy="install-allowed", priority=50)
|
||||
|
||||
|
||||
def test_remove_source_does_not_crash_on_invalid_ipv6(tmp_path: Path):
|
||||
project = tmp_path / "proj"
|
||||
(project / ".specify").mkdir(parents=True)
|
||||
with pytest.raises(BundlerError, match="No project-scoped catalog source"):
|
||||
cc.remove_source(project, "https://[::1/c.json")
|
||||
|
||||
Reference in New Issue
Block a user