DEV Community

StarkMan
StarkMan

Posted on

CVE-2026-94545: when the social-card renderer becomes an unauthenticated code path

CVE-2026-94545: when the social-card renderer becomes an unauthenticated code path

Open Graph images are the least interesting part of a web application, which is why they rarely get a security review. On 23 September 2026, Vercel shipped Next.js 16.3.6 to fix CVE-2026-94545, a remote code execution flaw reachable through the module that generates those images. The vulnerable path needs no authentication and no user interaction. A single request to an Open Graph route is enough.

What the module actually does

The next/og module turns a JSX description into a PNG in two steps. Satori renders the JSX into SVG, then sharp rasterizes that SVG into a PNG. The default runtime is Node.js, and the routes that expose this work are usually public, because their whole purpose is to be fetched by social platforms.
The flaw sits in the first step. Satori does not escape text content when it serializes inline SVG elements, a CWE-116 output-encoding problem. Text a caller controls therefore lands inside an XML document as markup rather than as data.

From escaped text to code execution

Once attacker-controlled text becomes markup, the SVG handed to sharp is no longer just a picture description. sharp delegates to native libraries, and for SVG input those are libvips, librsvg and libxml2. A crafted document reaches those parsers and triggers memory corruption, which yields command execution with the privileges of the Next.js server process.
Two conditions decide whether a deployment is exposed. The Open Graph route must run on the Node.js runtime, and sharp must be installed. Both hold for the common install path, including the official image and most production deployments. Switching the route to the edge runtime, or removing sharp so rendering goes through the sandboxed resvg-wasm renderer, breaks the chain that leads to code execution.
The published analysis also records a practical detail: exploitation is blind and replaces the worker process, so a successful attempt tends to surface as a brief service interruption rather than as a quiet foothold.

Why image pipelines keep producing execution bugs

Image rendering is a parsing problem in disguise. A modern social-card route accepts structured input, serializes it into one document format, and then hands that document to a chain of native parsers written for performance, not for hostile input. Every handoff assumes the previous layer produced well-formed data.
That assumption is what CVE-2026-94545 breaks. The escaping step that should have kept data as data did not run, and every layer below treated the result as trusted. The same pattern shows up in template injection, in XML external entity handling, and in the long history of image decoders that turn a file into memory corruption. The novelty here is the location: an unauthenticated route most teams think of as cosmetic.

What to do

Upgrade Next.js to 16.3.6 or later and Satori to 0.33.5 or later. Satori 0.33.5 adds the escaping that the vulnerable versions lacked, and patching only one of the two components leaves the injection point in place.
If an immediate upgrade is not possible, the advisory lists three temporary measures: move the Open Graph route to the edge runtime so rendering uses resvg-wasm, remove the sharp dependency so the native parsing chain is never reached, or put authentication or an allowlist in front of the Open Graph route. None of them replaces the upgrade, because the encoding defect remains until Satori is updated.
Inventories are the part worth doing beyond the patch. A route that takes unauthenticated input and feeds it into a native parser belongs in the same register as any other public-facing endpoint, and the Next.js version behind each one is a fact worth recording rather than assuming.

References

Top comments (0)