Next.js ImageResponse RCE fix: safe share card from a Sume job
Next.js 16.3.6 patched a critical ImageResponse RCE. After upgrading, build a share-card route that reads the Sume artifact server-side, not from the URL.

If your Next.js app renders share cards with ImageResponse from next/og, upgrade to 16.3.6 or later today. On September 22 the Next.js team published an out-of-band security update for a critical remote code execution issue in the Node.js ImageResponse (Next.js security update, read 2026-10-04). It affects versions >=16.2.0 <16.3.6. The Edge ImageResponse is not affected, and 15.x received hardening only, with 15.5.26 as the patched line.
The September 30 scheduled release moved the supported lines to 16.3.8 and 15.5.27 and fixed further issues, so pin to at least that if you can (September 2026 security release, read 2026-10-04). The rest of this post is about the part you control: how a route that composes a Sume generation into a card should get its inputs.
Do not take the image URL from the request
The tempting route is /api/card?img=https://...&title=..., which turns your server into a renderer for whatever a visitor passes. A safer shape takes only a Sume job id. The server reads the job from GET /v1/jobs/{id} with your key, checks that it is completed, and uses the first artifact's url. Sume artifacts are served from https://media.sume.com/artifacts/..., and the docs say to use these Sume media URLs from the result, since raw provider URLs are not public API outputs (Jobs and results).
Keep the title short and fixed-length on the server side too. Text that arrives from a form or a prompt is the input class that renderer bugs tend to involve, so treat it as untrusted even on a patched version.
A route handler that reads the job first
The handler below calls the Sume jobs endpoint with the x-api-key header, refuses anything that is not a completed image artifact on media.sume.com, and renders a 1200 by 630 card. It runs on the Node runtime, which is the one the advisory concerns, so run it only on a patched release.
import { ImageResponse } from "next/og";
export const runtime = "nodejs";
export async function GET(req: Request) {
const id = new URL(req.url).searchParams.get("job") ?? "";
if (!/^[A-Za-z0-9_-]{6,80}$/.test(id)) return new Response("bad id", { status: 400 });
const res = await fetch(`https://api.sume.com/v1/jobs/${id}`, {
headers: { "x-api-key": process.env.SUME_API_KEY! },
cache: "no-store",
});
if (!res.ok) return new Response("not found", { status: 404 });
const body = await res.json();
const job = body.data ?? body;
const art = job.result?.artifacts?.[0];
if (job.status !== "completed" || art?.type !== "image") {
return new Response("not ready", { status: 409 });
}
if (new URL(art.url).host !== "media.sume.com") {
return new Response("unexpected host", { status: 502 });
}
return new ImageResponse(
(<div style={{ display: "flex", width: "100%", height: "100%" }}>
<img src={art.url} width={1200} height={630} style={{ objectFit: "cover" }} />
</div>),
{ width: 1200, height: 630 },
);
}Checks to run after the upgrade
- Run
npm ls nextin every deployed app and confirm the resolved version is 16.3.6 or newer, or 15.5.26 or newer on the 15 line. - Search the codebase for
ImageResponseand note which routes run on the Node runtime versus Edge. - Confirm the job response shape in your own account with one real call, since the sample above reads
data.result.artifactsas documented. - Log the Sume
request_idfrom failed job reads so a bad card can be traced back to one API call.
Sources
Related posts
More in Developers
- Next.js 16.3.8 dev-server MCP disclosure and where the Sume key lives
Next.js 16.3.8 fixes a low-severity dev-server MCP disclosure and a high-severity image SSRF. How to keep a Sume API key server-side as you upgrade.
- Next.js 16.3.8 route handler: a GET-only Sume job status proxy
A Next.js route handler that proxies only GET /v1/jobs/{id}/status to Sume, validates the id and keeps the key server-side. Written for 16.3.8.
- Next.js use cache leak fix: keep Sume job reads out of the cache
Next.js 16.3.8 fixed use cache leaks, including Draft Mode content. A Sume job status read is live, per-workspace data, so fetch it uncached.
- Node 24.21 MIMEType.parse: validate a Sume artifact content type
Node 24.21.0 adds a non-throwing MIMEType.parse. Use it, with a try/catch fallback for older Node, to check a Sume artifact's content_type before saving.
Written by Sume