DEV Community

Cover image for SVG Serialization Is a Security Boundary
Svg/icons
Svg/icons

Posted on

SVG Serialization Is a Security Boundary

When an application generates an SVG, it is tempting to think of the result as an image.

But before it becomes pixels, SVG is structured markup.

That distinction matters whenever untrusted data is involved.

A recent vulnerability in Satori — which also affected the Node.js ImageResponse path in Next.js — provides a useful example of why SVG serialization should be treated as a security boundary.

What happened?

Satori converts HTML and JSX-like structures into SVG.

A security issue was discovered in the way certain values were escaped before being inserted into generated SVG output.

Under the right conditions, attacker-controlled values could be interpreted as SVG markup instead of remaining plain data.

The issue was fixed in Satori 0.33.5.

The interesting part is what can happen after that SVG is generated.

Next.js uses this rendering pipeline in the Node.js implementation of ImageResponse from next/og.

For affected Next.js 16 versions, applications passing attacker-controlled values into SVG content, attributes or styles could ultimately expose themselves to remote code execution.

The affected range for this specific advisory is:

Next.js >= 16.2.0 and < 16.3.6
Enter fullscreen mode Exit fullscreen mode

The specific fix landed in Next.js 16.3.6.

Applications using the Edge implementation of ImageResponse, or applications that do not pass attacker-controlled values into SVG content, attributes or styles, are not affected by this issue.

Next.js subsequently published its September 2026 security release and recommends upgrading to the current patched releases rather than stopping at the first version containing this specific fix.

The interesting part is not Next.js

For an affected application, the immediate action is straightforward:

patch the dependency.

But there is a broader lesson here for anyone building systems that generate SVG.

Consider a simplified pipeline:

USER INPUT
    ↓
APPLICATION DATA
    ↓
SVG SERIALIZER
    ↓
<svg>...</svg>
    ↓
RENDERER / CONVERTER / BROWSER
Enter fullscreen mode Exit fullscreen mode

One of the important trust boundaries sits here:

APPLICATION DATA
    ↓
[ ESCAPE / VALIDATE ]
    ↓
SVG SERIALIZER
Enter fullscreen mode Exit fullscreen mode

Once application data becomes markup, the rules change.

A string that is harmless as application data may have a completely different meaning when inserted into an XML element, attribute, style declaration or another serialized structure.

This is not unique to SVG.

Developers already think this way about HTML generation, SQL queries, shell commands and templating systems.

SVG deserves the same mental model.

Generated SVG is not automatically trusted SVG

There is an easy assumption to make:

We generated the SVG ourselves, so it must be trusted.

But the application may control the SVG structure while an external user controls some of the values inserted into it.

For example:

<svg>
  <text>{userProvidedTitle}</text>
</svg>
Enter fullscreen mode Exit fullscreen mode

The <svg> structure belongs to the application.

userProvidedTitle does not.

The serializer has to preserve that distinction.

If escaping fails, data may cross the boundary and become syntax.

That is the core issue.

Context matters after serialization too

There is another interesting lesson in this vulnerability.

The Satori advisory rates the escaping issue itself as moderate severity.

But the impact depends on what consumes the generated SVG afterward.

In the affected Next.js Node.js path, the consequences can become much more serious.

So a security review of an SVG pipeline should not stop at:

Can this library generate valid SVG?
Enter fullscreen mode Exit fullscreen mode

It should also ask:

Where does the generated SVG go next?
Enter fullscreen mode Exit fullscreen mode

A generated SVG might be:

  • sent directly to a browser;
  • rasterized into PNG;
  • passed to another parser;
  • converted by a native library;
  • cached by a server;
  • embedded into another document;
  • processed by an image-generation service.

The same serialization weakness can have very different consequences depending on the next component in the pipeline.

Three practical rules

For developers generating SVG dynamically, three rules are worth keeping in mind.

1. Treat serialization as a security boundary

Do not assume that values are safe simply because your application created the SVG structure.

Untrusted values remain untrusted until they have been correctly encoded for the context in which they are inserted.

2. Patch the whole pipeline

Knowing which library creates your SVG is not enough.

Track the components that parse, serialize, optimize, render and convert it.

A vulnerability can originate in one component and become significantly more serious because of what happens later in the pipeline.

3. Minimize what untrusted input can control

Where possible, avoid allowing external input to define arbitrary SVG markup, attributes or styles.

For many applications, external data only needs to control a limited set of values such as text, predefined colors or numeric dimensions.

Reducing that surface makes the pipeline easier to understand and easier to secure.

SVG is an image format — and markup

Developers often work with SVG alongside PNG, WebP or JPEG.

That can hide an important architectural difference.

Raster formats primarily describe pixels.

SVG describes a document.

And documents are parsed.

When SVG is generated dynamically, the transition from data to document syntax deserves the same attention we already give other serialization boundaries.

The recent Satori and Next.js vulnerabilities are specific bugs affecting specific versions.

They do not mean that dynamically generated SVG is inherently unsafe.

But they provide a useful reminder:

the moment untrusted data becomes SVG markup, serialization becomes part of your security model.


Sources

Top comments (0)