Harden CalDAV sync handling

This commit is contained in:
2026-07-11 18:37:51 +02:00
parent 9bcf41bb1f
commit c071235ad7
2 changed files with 17 additions and 3 deletions

View File

@@ -151,6 +151,8 @@ def validate_http_url(url: str, *, label: str) -> str:
parsed = urllib.parse.urlparse(url)
if parsed.scheme not in {"http", "https"} or not parsed.netloc:
raise CalendarError(f"{label} must be an absolute HTTP(S) URL")
if parsed.username or parsed.password:
raise CalendarError(f"{label} must not include embedded credentials")
return urllib.parse.urlunparse(parsed)
@@ -748,9 +750,10 @@ def http_request(
timeout: int = 30,
) -> tuple[int, dict[str, str], str]:
data = body.encode("utf-8") if isinstance(body, str) else body
url = validate_http_url(url, label="Calendar source URL")
request = urllib.request.Request(url, data=data, method=method, headers=headers or {})
try:
with urllib.request.urlopen(request, timeout=timeout) as response: # noqa: S310 - URLs are admin-configured sync sources.
with urllib.request.urlopen(request, timeout=timeout) as response: # noqa: S310 - validated admin-configured sync source URL. # nosemgrep: python.lang.security.audit.dynamic-urllib-use-detected.dynamic-urllib-use-detected
response_headers = {key.lower(): value for key, value in response.headers.items()}
payload = response.read().decode(response_headers.get("content-charset") or "utf-8", errors="replace")
return int(response.status), response_headers, payload