feat: validate and unblock media downloads

This commit is contained in:
ik
2026-09-12 15:54:53 +07:00
parent bda0a0ef5e
commit 26724c7675
6 changed files with 72 additions and 21 deletions
+28 -4
View File
@@ -1,6 +1,7 @@
from __future__ import annotations
import hashlib
import io
import json
import mimetypes
import re
@@ -10,6 +11,9 @@ from pathlib import Path
from urllib.parse import urljoin, urlsplit
from bs4 import BeautifulSoup, Tag
from PIL import Image, UnidentifiedImageError
MAX_IMAGE_PIXELS = 40_000_000
@dataclass(frozen=True, slots=True)
@@ -91,12 +95,32 @@ def reclassify_manifest(path: Path) -> dict:
return manifest
def store_asset(root: Path, body: bytes, *, content_type: str, source_url: str) -> tuple[str, str]:
def inspect_image(body: bytes) -> tuple[int, int, str]:
try:
with Image.open(io.BytesIO(body)) as image:
width, height = image.size
image_format = image.format
image.verify()
except (UnidentifiedImageError, OSError, ValueError) as exc:
raise ValueError("asset is not a valid raster image") from exc
if width < 1 or height < 1 or width * height > MAX_IMAGE_PIXELS:
raise ValueError("asset dimensions are outside safe limits")
mime = Image.MIME.get(image_format or "")
if mime not in {"image/jpeg", "image/png", "image/webp", "image/gif"}:
raise ValueError(f"unsupported image format: {image_format}")
return width, height, mime
def store_asset(root: Path, body: bytes, *, content_type: str, source_url: str) -> tuple[str, str, int, int, str]:
width, height, detected_mime = inspect_image(body)
declared_mime = content_type.split(";", 1)[0]
if declared_mime != detected_mime:
raise ValueError(f"image MIME mismatch: declared {declared_mime}, detected {detected_mime}")
digest = hashlib.sha256(body).hexdigest()
extension = mimetypes.guess_extension(content_type.split(";", 1)[0]) or Path(urlsplit(source_url).path).suffix
extension = extension if extension in {".jpg", ".jpeg", ".png", ".webp", ".gif", ".svg"} else ".bin"
extension = mimetypes.guess_extension(detected_mime) or Path(urlsplit(source_url).path).suffix
extension = ".jpg" if extension == ".jpe" else extension
target = root / "files" / digest[:2] / f"{digest}{extension}"
target.parent.mkdir(parents=True, exist_ok=True)
if not target.exists():
target.write_bytes(body)
return digest, str(target.relative_to(root))
return digest, str(target.relative_to(root)), width, height, detected_mime