"""Regression tests for the 2026-09-03 adversarial-review findings. Source of truth: .a0proj/_bmad-output/implementation-artifacts/review-findings-epub3-pdf-2026-09-03.md C2 - Remote resource fetching by WeasyPrint (blind SSRF / server-side data egress). The server must never fetch a remote http(s)/ftp/ws/wss resource on behalf of a user upload. The fix lives in converters.common._blocking_url_fetcher (common.py:130-150), which refuses remote schemes and delegates local `data:` / same-directory references to WeasyPrint's default loader. The import that makes that delegation possible is converters.common:18. Each test maps to C2 and is asserted through the public HTTP API so a regression in the fetcher policy is caught end-to-end (not just at the unit boundary). Satisfies: C2 """ import base64 import io import app from tests.helpers import wait_for_job def _upload(client, content, filename="doc.html"): """POST an upload, wait for the terminal job state, return the snapshot.""" files = {"file": (io.BytesIO(content.encode("utf-8")), filename)} resp = client.post("/api/convert", data=files, content_type="multipart/form-data") assert resp.status_code == 202, resp.get_json() return wait_for_job(client, resp.get_json()["job_id"]) # --------------------------------------------------------------------------- # Finding C2: WeasyPrint SSRF guard - remote resource references are refused # --------------------------------------------------------------------------- def test_remote_http_image_reference_rejected(client): """A user-supplied .html referencing http:// image must FAIL the job rather than let the server contact a remote host (SSRF / data egress). Satisfies: C2 """ html = ( "Remote Img" 'remote' "" ) job = _upload(client, html) assert job["status"] == "error", job assert "blocked" in job["error"].lower() or "remote" in job["error"].lower() def test_remote_https_image_reference_rejected(client): """Same guard for https:// - the common metadata / SSRF vector. Satisfies: C2 """ html = ( "" '' "" ) job = _upload(client, html) assert job["status"] == "error", job assert "blocked" in job["error"].lower() or "remote" in job["error"].lower() # --------------------------------------------------------------------------- # Finding C2 (regression): local data: references remain permitted # --------------------------------------------------------------------------- def test_local_data_uri_image_succeeds(client): """A local `data:` URI resolves through WeasyPrint's default loader and the conversion completes. Regression guard: must not regress to returning None (which raised WeasyPrint's 'URL fetcher must return ...' assertion). Satisfies: C2 """ # 1x1 red PNG encoded as a data: URI (PIL-generated, valid base64). png = base64.b64decode( "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC" ) data_uri = "data:image/png;base64," + base64.b64encode(png).decode("ascii") html = ( "Local Img" 'local' "" ) job = _upload(client, html) assert job["status"] == "done", job