mirror of
https://github.com/makeplane/plane.git
synced 2026-09-01 19:48:42 +02:00
isSafeImageSrc only validated the URL handed to <Image src>, before render. The actual fetch happens inside @react-pdf/image's fetchRemoteFile, which follows redirects by default and never re-consults the guard on the redirect target — so a URL on an ordinary public host could 302 to an internal address (cloud metadata, a Docker service name, loopback) and be fetched anyway, no DNS control required. Close it the same way imageComponent asset images are already handled: pre-fetch image-node srcs before rendering starts, instead of handing a raw URL to the renderer. Added fetchImageSrcSafely, which fetches with redirect: "manual" and re-validates every hop against isSafeImageSrc, capped at 5 redirects. pdf-export.service.ts now extracts external image srcs alongside asset ids and resolves both into the same data-URI map before the synchronous render pass runs; node-renderers.tsx's image renderer looks up that pre-resolved value instead of taking the raw src. Also switched the pre-existing per-asset URL resolution loop in processImages to Promise.all, since it was already independent per asset and needed to satisfy the same lint rule the new redirect-following code does (which, unlike that loop, is genuinely sequential by nature). Documented the residual DNS-rebinding TOCTOU that remains on the final, non-redirect hop: isSafeImageSrc judges a hostname once, and the actual fetch resolves DNS again independently, so a name that changes address between those two lookups is still unguarded. Re-validating every redirect hop closes the far more easily exploited "one crafted HTTP response" gap; it does not add DNS pinning. Co-authored-by: Plane AI <noreply@plane.so>