react-native-svg-transformer is a Metro transformer that turns imported .svg files into React components, and it is safe for production use as long as you treat it as build-time tooling and vet its dependency tree the same way you would any other package. It does not ship code into your app bundle by itself; instead it hooks into the Metro bundler so that import Logo from './logo.svg' returns a renderable component backed by react-native-svg.
That build-time position is the whole security story. A transformer runs on your CI machine and on every developer laptop, with full access to the filesystem and network during a build. So the questions that matter are not "does this render my icon correctly" but "what runs when Metro invokes it, and what does it depend on."
How the transformer fits into Metro
Metro, the React Native bundler, lets you replace its default transformer. You point metro.config.js at the package and register svg as a source extension:
const { getDefaultConfig } = require('expo/metro-config');
const config = getDefaultConfig(__dirname);
config.transformer.babelTransformerPath = require.resolve(
'react-native-svg-transformer'
);
config.resolver.assetExts = config.resolver.assetExts.filter(
(ext) => ext !== 'svg'
);
config.resolver.sourceExts = [...config.resolver.sourceExts, 'svg'];
module.exports = config;
Under the hood the transformer parses the SVG with svgr, produces JSX, and hands it back to Metro to compile. The runtime rendering is done by react-native-svg, which is a peer dependency you install separately. That separation matters: the transformer is a devDependency, and react-native-svg is the runtime library that actually ships.
What is in the dependency tree
The chunk of trust you take on is mostly @svgr/core and its plugins, plus Babel machinery. None of this executes in your shipped app, but all of it executes during your build. Run an audit before you adopt it:
npm ls react-native-svg-transformer
npm audit --omit=dev=false
The second flag matters here because build tooling lives in devDependencies, and a plain npm audit --production would skip exactly the packages you care about for a transformer. A build-time compromise can inject code into the bundle that a runtime-only scan never sees, which is why the SBOM you generate should include dev dependencies. An SCA tool can flag transitive advisories across both trees and tell you which ones actually reach a build step.
The build-time trust boundary
The realistic threat with any Metro transformer is a compromised release in the dependency chain, not a bug in the SVG parsing itself. If an attacker publishes a malicious version of a deep dependency, it runs with your CI credentials the next time you build. Two habits contain that:
- Pin exact versions and commit a lockfile.
npm ciin CI installs only what the lockfile records, so a freshly-published bad version cannot slip in silently. - Gate dependency updates behind review. Renovate or Dependabot PRs should show you the changelog and the diff before a transformer bump merges.
Neither of these is specific to this package, but transformers are a higher-value target than most because of where they run.
Pairing it with react-native-qrcode-svg
A common companion in React Native apps is react-native-qrcode-svg, which renders QR codes as SVG using the same react-native-svg runtime. It is a runtime dependency, not a build transformer, so its trust profile is different: its code ships in your app. The thing to watch there is the data you encode. A QR code that embeds a user-controlled URL is a redirect primitive, so validate and allowlist what you encode before generating the code, the same way you would validate any outbound link.
Because both libraries sit on top of react-native-svg, keep that single runtime dependency current. Version drift between the transformer's expectations and the installed react-native-svg is the most common source of "SVG renders on iOS but not Android" bug reports, and pinning avoids it.
A practical adoption checklist
Before you add the transformer to a real project:
- Confirm it lives in
devDependencies, notdependencies. - Generate an SBOM that includes dev dependencies and scan it.
- Pin the version and commit the lockfile; use
npm ciin CI. - Restrict SVG sources to files in your own repository, not fetched at build time from a URL.
- Keep
react-native-svgon a single pinned version shared across the transformer and any SVG-rendering libraries like react-native-qrcode-svg.
Static SVG files bundled from your own repo carry very little runtime risk. The transformer strips scripts during conversion, and React Native has no DOM for an embedded <script> to execute against anyway. The exposure that deserves your attention is the build pipeline, and that is manageable with lockfiles and dependency review.
FAQ
Does react-native-svg-transformer add code to my production bundle?
No. It is build-time tooling that converts SVG files into components during bundling. The rendering code that ships comes from react-native-svg, which you install as a separate runtime dependency.
Is it safe to render SVGs from a remote URL with this setup?
The transformer only handles SVGs imported as local files at build time. Rendering remote SVG content is a runtime concern handled by react-native-svg, and you should validate and sanitize any remote source before rendering it.
How does react-native-qrcode-svg relate to it?
react-native-qrcode-svg is a runtime library that draws QR codes using the same react-native-svg backend. It is not a transformer, so its code ships in your app. Validate the data you encode into QR codes, since a QR can carry a user-controlled URL.
What is the biggest security risk with a Metro transformer?
A compromised dependency in the transformer's tree running with your CI credentials at build time. Pinning versions, committing a lockfile, and reviewing dependency-bump PRs are the controls that matter most.