mirror of
https://github.com/vercel/next.js.git
synced 2026-09-20 02:25:18 +08:00
806fbd4367
Fork PR #96621 by @ceolinwill, re-opened as a branch PR so the "when deployed" CI job can run — it requires Vercel deployment secrets that GitHub does not expose to pull requests from forks, so it can never pass on the original. **The commit is unchanged and still authored by @ceolinwill.** Please credit them; #96621 should be closed in favor of this one. ### What? `getSharp()` calls `_sharp.block({ operation: ['VipsForeignLoad'] })` to block every image loader, then unblocks a specific allowlist — and that allowlist omitted `VipsForeignLoadSvg`. Because `_sharp` is a module-level singleton, the block is process-wide and permanent: the first `/_next/image` request in a process permanently disables Sharp's SVG loader. `ImageResponse` (`next/og`) rasterizes via resvg and then hands SVG to Sharp, so once that loader is blocked it fails. The symptom is worse than a bad image — the render throws `Input buffer contains unsupported image format`, which surfaces as a **socket hang up / crashed response** on any `ImageResponse` route requested after an uncached image optimization in the same process. Introduced by #96301, which aligned the Sharp allowlist with `detectContentType()` but missed SVG. Fixes #96612 ### How? Adds `'VipsForeignLoadSvg'` to the unblock list. This does not weaken SVG protections for user-supplied images. `detectContentType()` already returns SVG, and untrusted SVG is gated separately by `dangerouslyAllowSVG`, which throws a 400 in `imageOptimizer()` before Sharp is ever invoked. Unblocking the loader only restores Sharp's ability to process SVG that Next.js itself generates. ### Tests The existing `og-api` test is extended to reproduce the exact same-process ordering: render `/og-node`, perform an uncached `/_next/image` optimization (asserting `x-nextjs-cache: MISS`, with a random URL so it can't be served from cache), then render `/og-node` again. Verified locally that this fails without the one-line fix (`socket hang up`, caused by `Input buffer contains unsupported image format`) and passes with it. No regressions in the SVG security coverage — `test/e2e/image-optimizer/dangerously-allow-svg.test.ts` passes 94/94 including all `maintain vector svg` / blur-svg cases, and `test/e2e/image-optimizer/image-optimizer.test.ts` plus the `og-*` suites are green. Co-authored-by: ceolinwill <4393133+ceolinwill@users.noreply.github.com>