Harden release artifact publication

This commit is contained in:
2026-07-22 20:41:42 +02:00
parent 35c346a1fa
commit 4dc0c8d013
5 changed files with 1057 additions and 20 deletions

View File

@@ -9,6 +9,7 @@ import re
from typing import Any
from .catalog import DEFAULT_PUBLIC_BASE_URL, canonical_hash
from .candidate_artifact import validate_release_channel
from .release_intelligence import compatibility_rows, module_rows, signature_rows
@@ -42,6 +43,7 @@ def module_directory_payloads(
channel: str,
public_base_url: str = DEFAULT_PUBLIC_BASE_URL,
) -> tuple[tuple[Path, dict[str, Any]], ...]:
channel = validate_release_channel(channel)
generated_at = json_datetime(datetime.now(tz=UTC))
modules = module_rows(catalog_payload)
compatibility = compatibility_rows(modules)
@@ -59,8 +61,8 @@ def module_directory_payloads(
if not module_id:
continue
version = str(module.get("version") or "0.0.0")
module_slug = safe_path_part(module_id)
version_slug = safe_path_part(version)
module_slug = safe_module_id(module_id)
version_slug = safe_version(version)
module_base = f"{base_url}/catalogs/v1/modules/{module_slug}"
manifest_url = f"{module_base}/{version_slug}/manifest.json"
module_index_url = f"{module_base}/index.json"
@@ -139,7 +141,25 @@ def module_directory_payloads(
def safe_path_part(value: str) -> str:
return re.sub(r"[^A-Za-z0-9_.-]+", "_", value.strip()) or "_"
if (
not isinstance(value, str)
or value in {".", ".."}
or re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9_.+!-]{0,127}", value) is None
):
raise ValueError("module-directory path part is not canonical")
return value
def safe_module_id(value: str) -> str:
if re.fullmatch(r"[a-z][a-z0-9_-]{0,63}", value) is None:
raise ValueError("module ID is not canonical")
return safe_path_part(value)
def safe_version(value: str) -> str:
if re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9._+!-]{0,127}", value) is None:
raise ValueError("module version is not canonical")
return safe_path_part(value)
def json_datetime(value: datetime) -> str: