Build1 publisher2 min readPublished
Satori's SVG escaping flaw reaches remote code execution through Next.js ImageResponse on Node
Satori's SVG escaping flaw exposes Next.js 16.2.0 and every release before 16.3.6 to remote code execution when apps pass attacker input to next/og on Node. The step where app data becomes SVG markup needs the escaping discipline teams already give HTML and SQL.
The Engineer · Build desk
Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction
What happened
- Satori, which turns JSX-like structures into SVG, mis-escaped certain values, so attacker-controlled strings could be parsed as SVG markup instead of staying plain data.
- Satori fixed the escaping in version 0.33.5, and Next.js carries its own fix for the advisory in 16.3.6.
- Apps using the Edge implementation of ImageResponse, or keeping attacker-controlled values out of SVG content, attributes and styles, fall outside the advisory.
- Next.js has since issued a September 2026 security release and tells users to move to the current patched releases instead of stopping at 16.3.6.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- decision A lockfile pinned at 16.3.6 clears this advisory yet still sits behind the release Next.js now tells teams to run, so the upgrade target is the newest patch.
- exposure Teams calling Satori directly have to judge their risk by whatever reads its SVG next, since the moderate rating covers the library alone.
- cost Image routes that let a request set raw styles or attributes need rework into typed inputs, a bigger job than the version bump.
Satori's own advisory rates the escaping issue as moderate severity, according to a write-up of the case on dev.to [10]. Next.js runs that same rendering pipeline inside the Node.js implementation of ImageResponse [3]. On that path, an application that passes attacker-controlled values into SVG content, attributes or styles could be exposed to remote code execution [6]. The post argues that impact depends on what consumes the SVG next [11]. Its candidates include a browser, a PNG rasterizer, another parser, a native conversion library, a server cache and an image-generation service [11].
The write-up does not describe the step from injected markup to code execution, or why the Edge build of ImageResponse avoids it [8]. Scoping therefore rests on the advisory's conditions. A version check cannot settle the input-flow condition. The post's example is a title field: the application owns the `<svg>` and `<text>` elements, and `userProvidedTitle` belongs to someone else [12]. The serializer has to preserve that distinction for every value it writes [12].
The post names the assumption behind this class of bug: "We generated the SVG ourselves, so it must be trusted." [15] Developers already escape by context when they build HTML, SQL queries, shell commands and templates, the post notes [14]. SVG slips past that habit because teams file it as an image, and injection bugs have never cared much about file extensions. Before anything rasterizes it, SVG is structured markup [16].
The design fix is to shrink what outside input can say. The post suggests most applications only need external data to set text, predefined colors and numeric dimensions [13]. In my context I would build that as typed fields. A string only ever lands in a text node. A color comes from a fixed enum. A number is parsed and clamped before it reaches an attribute. Free-form style input from a request is the first thing I would remove, because styles are one of the three injection points the Next.js advisory names [6].
What to watch
- Publication of the chain from injected SVG markup to code execution in the Node path, which would show whether other Satori consumers face the same outcome.
- Later Next.js security releases that touch the next/og Node.js rendering path again.