Five Attack Vectors Hidden Inside Malicious SVG Files

  • Inline <script> elements: Execute with full origin cookies and localStorage access if a user opens https://yourapp.com/uploads/logo.svg directly in a browser tab.
  • Inline event handlers: <svg onload="fetch(...)">, onerror, onmouseover, or SMIL <set attributeName="onmouseover" ...>.
  • javascript: and data: URIs: Inside <a>, <use>, or <image> href / xlink:href attributes.
  • <foreignObject> HTML injection: Embeds arbitrary HTML (<iframe>, <form>) inside an SVG coordinate box.
  • XML External Entities (XXE) & SSRF: Legacy server-side XML parsers resolving <!ENTITY> declarations or remote http:// stylesheet/image fetches.

Defense-in-Depth: Sanitizer + Rendering Context + HTTP Headers

On SVG Nexus, catalog files are sanitized against scripts, external entities, and remote references before serving, and both the Online SVG Editor and SVG Optimizer strip dangerous script and event attributes client-side when cleaning files. Important caveat: never rely on client-side tools alone for untrusted user uploads in your own backend! Enforce all three server controls:

Sanitizing untrusted SVG strings with DOMPurify + locked-down HTTP response headers
import DOMPurify from "isomorphic-dompurify";

export function sanitizeUserSvg(rawXml: string): string {
  return DOMPurify.sanitize(rawXml, {
    USE_PROFILES: { svg: true, svgFilters: true },
    FORBID_TAGS: ["script", "foreignObject", "iframe", "object", "embed"],
    FORBID_ATTR: ["onload", "onerror", "onclick", "onmouseover", "xlink:href"],
  });
}

// Required HTTP headers when serving user-uploaded SVGs (ideally from a separate sandbox CDN domain):
// Content-Type: image/svg+xml
// X-Content-Type-Options: nosniff
// Content-Security-Policy: default-src 'none'; style-src 'unsafe-inline'; sandbox

Finally, render user-supplied SVGs exclusively via <img src="https://cdn-userdata.example/u12.svg" alt="">—never dangerouslySetInnerHTML—and serve user uploads from a separate cookieless asset domain.