Skip to content

[SECURITY][MEDIUM] data:image/svg+xml accepted as graphic URL — SVG with embedded scripts exploitable via object/embed elements #54

Description

@LucasMaupin

Summary

isValidGraphicUrl() in GraphicsPanel.tsx accepts any data:image/ URI, including data:image/svg+xml. SVG files can contain embedded <script> elements. When an SVG is rendered via <img> the browser sandboxes scripts — but if the URL is ever used in <object>, <embed>, or <iframe> (as Strom's headless browser renderer may do with graphic overlay URLs), scripts execute in the page context. SVG SMIL animation event handlers also trigger JavaScript without <script> blocks, bypassing naive content-type checks.

This is distinct from #41 (data:text/html XSS) and represents a separate injection vector via the image/SVG MIME type.

CVSS Score

4.6 (Medium) — CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N

Category

OWASP A03:2021 – Injection

Affected File(s)

  • src/pages/SetupPage/GraphicsPanel.tsx line 16 — isValidGraphicUrl() validator

Steps to Reproduce

  1. As an authenticated operator, configure a Graphic URL as:
    data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg"><script>alert(1)</script></svg>
  2. The validator accepts this URL (it starts with data:image/).
  3. If the frontend or Strom loads this URL in an <object> or <iframe>, the script executes.

Remediation

Restrict data URI support to safe raster image formats only:

// GraphicsPanel.tsx isValidGraphicUrl()
const SAFE_DATA_PREFIXES = ['data:image/png', 'data:image/jpeg', 'data:image/gif', 'data:image/webp'];
if (SAFE_DATA_PREFIXES.some(p => s.startsWith(p))) return true;
// Explicitly reject: data:image/svg+xml, data:text/html

If SVG is required, serve it from a same-origin endpoint where CSP script-src 'self' applies, rather than accepting inline data URIs.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions