← Blog

SVG security — scripts, external references, sanitization

SVG can carry executable code and external requests; SVGtoPDF disables both Things SVG can do that worry security teams <script>alert('XSS')</script> JavaScript execution <use href="https://evil/x.svg#frag"/> external resource fetch <image href="https://evil/p.png"/> image fetched at render <link href="https://evil/style.css"/> external stylesheet XML entity expansion "billion laughs" attack on parsers XML external entity (XXE) local file disclosure via DTDs In SVGtoPDF No script execution, no remote fetching, no DTD/XXE evaluation. SVG processed as static markup; "code" inside is inert.

SVG looks like a graphics format but is technically a programming environment: scripts can execute, external resources can be fetched, XML entities can expand recursively, and various features overlap with attack surfaces. A naïve "render this SVG" pipeline can leak data, execute code, or exhaust memory. SVGtoPDF's renderer is designed to disable all of these classes of behavior.

JavaScript execution — disabled

SVG can include <script> tags with JavaScript that runs when the SVG is loaded by a browser. Used for interactive infographics, animated charts, dynamic data visualization.

For a renderer that only generates static output, JavaScript is unnecessary and dangerous. SVGtoPDF's renderer has never supported script execution; <script> tags are parsed as XML elements but never executed. A hostile SVG containing <script>document.cookie</script> renders as if the script tag weren't there.

External resources — not fetched

SVG can reference external resources via several mechanisms:

If a renderer fetches these during rendering, three risks:

  1. SSRF (server-side request forgery): a hostile SVG references internal URLs (http://localhost:8080/admin, http://169.254.169.254/aws-metadata/) and uses the renderer as a relay.
  2. User tracking: the SVG references an attacker-controlled URL; the fetch reveals the renderer's IP, user agent, and timing.
  3. Resource exhaustion: the SVG references a large or slow-responding URL, hanging the renderer.

SVGtoPDF does not fetch external resources during conversion. The renderer is configured with no network access. References to http:// or https:// URLs resolve to "missing resource" — the corresponding image or stylesheet is silently skipped.

The only way to include external content in an SVG processed by SVGtoPDF is to inline it (data URIs, embedded styles).

XML entity expansion — capped

XML allows entity definitions:

<!DOCTYPE svg [
  <!ENTITY a "1234567890">
  <!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;">
  <!ENTITY c "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
</>

This is the classic "billion laughs" denial-of-service: each entity references multiple instances of the previous one, so 9 levels of nesting expand to a billion characters. A naïve XML parser allocates that much memory.

SVGtoPDF's parser (libxml2) has entity expansion limits enabled. Documents that exceed the limits are rejected with a parser error. The default limit is conservative — well below the threshold that could cause memory exhaustion.

XXE — XML External Entities

XML allows entities to reference external resources:

<!DOCTYPE svg [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
</>
<svg ...>&xxe;</svg>

If the parser resolves external entities, the file's contents would be inlined into the SVG. A renderer that returns parsed SVG content (e.g. as a debugging string) could leak local files.

SVGtoPDF disables external entity resolution. Even if a hostile SVG has an XXE payload, the parser ignores the SYSTEM declaration; the entity reference resolves to nothing.

Output PDF safety

The PDF produced by SVGtoPDF is a standard, static PDF with no embedded JavaScript, no external resource references, no script triggers. PDFs in general can carry JavaScript (form actions, page-open scripts) but SVGtoPDF doesn't generate any.

The output is suitable for distribution: opening it in any PDF reader (Acrobat, Preview, browser-built-in) does not execute any code from the SVG source. Any "interactive" features in the SVG are flattened to their initial rendered state.

Size-based attacks

SVG can be syntactically small but expensive to render: a tiny XML file specifying millions of repeated path operations, or a few large filter chains, can take significant CPU and memory.

SVGtoPDF's renderer has time and memory limits via process-level constraints (resource limits set on the rendering subprocess). SVGs that exceed the limits time out; the conversion fails cleanly without affecting other requests.

Sanitization by design

SVGtoPDF does not actively "sanitize" input SVGs — it doesn't rewrite them to remove suspicious elements. Instead, the renderer is configured to ignore the dangerous features. The same SVG fed to a browser would behave differently (script would execute, externals would fetch); fed to SVGtoPDF, it converts as static graphics only.

If you're hosting SVGs from untrusted sources and serving them to your own users (separate from running them through SVGtoPDF), sanitization is recommended on the consuming side. Established SVG-sanitizing libraries exist for every major web stack; pick one that fits your environment.

Quickly checking an SVG for suspicious content

Open the SVG in a plain text editor and search for any of: <script, onload=, onerror=, http://, https://. Hits indicate script execution, event handlers, or external resource references — none of which affect SVGtoPDF's output but are worth knowing about if the SVG also goes elsewhere.

For SVGs you intend to upload to SVGtoPDF: external references are disabled, scripts are disabled, the conversion is safe. For SVGs you host on your own site for browser consumption, sanitize separately.