github/spec-kit · error · BundlerError
Refusing to download {label} over non-HTTPS URL: {url}
Error message
Refusing to download {label} over non-HTTPS URL: {url} What it means
Spec Kit enforces HTTPS for every bundle download URL. Plain HTTP is accepted only for the exact hosts localhost, 127.0.0.1, and ::1; every other scheme and host combination is rejected as BundlerError before network access. Redirect and final response URLs must satisfy the same policy.
Source
Thrown at src/specify_cli/commands/bundle/__init__.py:923
def _require_https(label: str, url: str) -> None:
from urllib.parse import urlparse
# urlparse / hostname access raise ValueError on a malformed authority;
# keep the documented BundlerError contract (older Pythons surface this via
# the .hostname access below rather than at the urlparse call).
try:
parsed = urlparse(url)
hostname = parsed.hostname
# Accessing ``port`` performs urllib's syntax/range validation.
_ = parsed.port
except ValueError:
raise BundlerError(
f"Refusing to download {label}: URL is malformed: {url}"
) from None
is_localhost = hostname in ("localhost", "127.0.0.1", "::1")
if parsed.scheme != "https" and not (parsed.scheme == "http" and is_localhost):
raise BundlerError(
f"Refusing to download {label} over non-HTTPS URL: {url}"
)
if not parsed.hostname:
raise BundlerError(f"Refusing to download {label} from URL with no host: {url}")
def _download_remote_manifest(
entry_id: str,
url: str,
*,
expected_sha256: str | None = None,
):
"""Fetch a remote bundle artifact over HTTPS and extract its manifest."""
import io
import tempfile
from pathlib import PurePosixPath
from urllib.parse import urlparse as _urlparse
View on GitHub (pinned to bf88c9f9a8)
Solutions
- Serve the artifact over HTTPS and update the catalog download_url to the HTTPS URL.
- For a local test server, use exactly `http://localhost`, `http://127.0.0.1`, or `http://[::1]`; `0.0.0.0` and other host names are intentionally rejected.
- If a redirect is involved, configure the redirect target to HTTPS so every hop passes the guard.
- If you do not control the catalog, install from a local bundle path or choose a catalog source with an HTTPS URL.
Example fix
# before "download_url": "http://artifacts.internal/my-bundle-1.0.0.zip" # after "download_url": "https://artifacts.internal/my-bundle-1.0.0.zip"
Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlparse
LOCAL_HOSTS = {"localhost", "127.0.0.1", "::1"}
def is_allowed_download_url(url: str) -> bool:
try:
p = urlparse(url)
host = p.hostname
_ = p.port
except ValueError:
return False
if not host:
return False
return p.scheme == "https" or (p.scheme == "http" and host in LOCAL_HOSTS) Try / catch
except BundlerError as exc:
if "non-HTTPS URL" in str(exc):
report_that_https_or_exact_localhost_is_required()
else:
raise Prevention
- Publish all custom catalogs and artifacts behind HTTPS by default.
- Do not rely on alternate local hostnames; use localhost, 127.0.0.1, or ::1.
- Check redirect chains with curl -IL and reject any HTTP hop.
When it happens
Trigger: A catalog entry has `ftp://`, `http://`, `git://`, or another non-HTTPS download_url for a non-localhost host, or an HTTPS download redirects to HTTP. The check also runs under --offline before the offline gate.
Common situations: Using an internal Artifactory/Nexus/GitLab server that is configured for HTTP only, testing against `http://0.0.0.0:8000` or an alternate localhost name, or a redirect chain that downgrades to HTTP.
Related errors
- Catalog url must use HTTPS (got {parsed.scheme}://). HTTP is
- Catalog entry '{resolved.entry.id}' has a non-HTTP(S) downlo
- Refusing to download {label}: URL is malformed: {url}
- Refusing to download {label} from URL with no host: {url}
- Failed to download bundle '{entry_id}' from {_source_desc}:
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/158f99583dd00529.
Report an issue: GitHub.