October 18, 2026
Your Next.js OG Image Pipeline Has a Critical RCE Vulnerability
A dependency you never call directly just became a remote code execution vector in your image generation pipeline. Thatβs the shape of theβ¦

By Marcus Rivera
4 min read
A dependency you never call directly just became a remote code execution vector in your image generation pipeline. That's the shape of the Next.js security update from September 22.
A dependency you never call directly just became a remote code execution vector in your image generation pipeline. That's the shape of the Next.js security update from September 22.
Here's what happened, without the marketing gloss: Next.js shipped next/og, a way to generate dynamic Open Graph images β the preview cards you see when a link gets shared on social media β using JSX and CSS instead of a headless browser or an external image service. Under the hood, the Node.js implementation of ImageResponse relies on Satori, a library that converts HTML/CSS into SVG. Satori had an escaping bug in its SVG output. That bug, combined with vulnerabilities in its upstream dependencies, opened a path to remote code execution in Next.js versions 16.2.0 through 16.3.5. The fix is version 16.3.6, and it works by bumping the vulnerable dependencies rather than rewriting ImageResponse itself. If you're on 15.5.x, you're not affected by the RCE, but 15.5.26 ships related hardening anyway.
If your reaction is "wait, my OG image generator can execute arbitrary code on my server," you're reading it correctly. That's the whole story in one sentence. Everything else is detail.
The Dependency Chain Behind next/og
This is worth sitting with for a second, because it's a clean example of something that's easy to say in the abstract and easy to ignore in practice: your attack surface is not the code you wrote. It's the code you wrote, plus every library you imported, plus every library those libraries imported, recursively, down to whatever depth npm ls gives up trying to render.
Nobody using next/og sat down and typed import satori from 'satori'. Most people using it probably don't know Satori is the thing doing the HTML-to-SVG conversion under the API surface. That's the point of the abstraction β you write JSX, you get an image, the conversion mechanics are Next.js's problem, not yours. Right up until the conversion mechanics have a bug, at which point they become very much your problem, on your production server, potentially without you knowing the dependency existed at all.
This isn't a knock on next/og specifically. It's what every abstraction does. It takes a genuinely annoying problem β generating social preview images used to mean running a headless Chrome instance or hitting a third-party image API β and turns it into a function call. That's a real win. Nobody wants to provision a Puppeteer instance just to render a title and a background gradient into a PNG. But the win comes with an invisible line item: you've inherited Satori's dependency tree, and by extension, whatever its dependencies inherit. You didn't choose those dependencies. You probably couldn't name them. You're responsible for them anyway.
Why "Critical Severity, Upgrade Your Dependency" Is Actually the Good Outcome
It's worth noticing what Vercel didn't have to do here. They didn't have to redesign next/og. They didn't have to deprecate the Node.js implementation and push everyone toward the Edge runtime (which, notably, is unaffected β worth remembering if you're choosing between the two for reasons other than security). They fixed it by upgrading the vulnerable upstream packages that Satori depends on. One version bump, patch applied, moving on.
That's the quiet benefit of building on an ecosystem instead of hand-rolling your own SVG renderer: when something breaks, the fix is usually "update the package," not "rewrite the subsystem." The cost of that convenience showed up today as a critical CVE. The benefit of that convenience is that the fix took one line in your package.json. Both of those are true at once, and neither cancels the other out. That's what a dependency actually is β not free code, not a liability, just delegated responsibility with a maintenance obligation attached.
The Immediate Risk: User Input in the ImageResponse Pipeline
If you're running Next.js 16.2.0 through 16.3.5 with the Node.js ImageResponse implementation anywhere in your app β dynamic OG images for blog posts, social cards for user profiles, anything that takes user-influenced input (a title, a username, a query param) and feeds it into ImageResponse β this isn't a "get to it next sprint" patch. User-influenced input into an SVG renderer with a known escaping vulnerability is close to the textbook definition of an exploitable path. Patch it first, read the rest of this after.
Beyond the immediate fix, the incident is a reasonable prompt to ask a question most teams never ask about their OG image generation: what actually goes into that image? If a username or a post title gets interpolated into the JSX you're passing to ImageResponse, you now have a concrete reason to think about that as user input hitting a rendering pipeline, not just a string going into a template. The vulnerability here lived in Satori's dependencies, not in how individual apps use next/og β but "the library had a bug" and "the library had a bug that was exploitable because of how untrusted input reached it" aren't mutually exclusive, and it's the second one that determines how urgently a given app needs to care.
Why This Dependency Lesson Will Still Matter Six Months From Now
Zoom out past this specific CVE and the pattern is durable: any feature that saves you from running a browser, a rendering service, or a build step is doing that by adding a rendering engine into your own process instead. That's a fair trade in a lot of cases. It's also a trade, not a free lunch, and the invoice doesn't come due until something like this happens.
Six months from now, this particular CVE will be patched everywhere it matters and mostly forgotten. The pattern behind it won't be. Every "just import this, it handles X for you" feature β image generation, PDF rendering, markdown-to-HTML, whatever the next one is β is quietly expanding the set of code that runs with your application's privileges. Nobody audits that expansion when they add the import. Almost everybody has to reckon with it later, usually via a GitHub security advisory landing in their inbox on a Tuesday.
The practical habit worth taking from this isn't "stop using next/og" or "distrust Vercel's security program" β their response here was fast and the fix was clean, which is what you want from a security process, not a reason to be nervous about it. The habit is smaller and less dramatic: when you adopt a feature that generates or renders something dynamically from data that includes user input, it's worth knowing, even loosely, what's doing the rendering underneath. Not because you're going to audit Satori's source. Because when the advisory shows up, you want to already know whether it applies to you, instead of finding out by reading a blog post about your own production incident.