I met with a fintech CTO in September 2024 who told me their mobile app's supply chain "was not really their problem" because the binaries were signed by Apple and Google. I asked her how many npm packages were in their React Native bundle. She did not know. We ran npm ls --prod --depth=999 on their repo and counted 1,420 JavaScript packages, plus 68 native modules across iOS and Android, plus CodePush for OTA updates. Every one of those is a potential supply chain vector that the App Store signing process does not mitigate.
React Native's supply chain is larger and stickier than a web app's. Larger because it has JS plus native plus OTA layers. Stickier because a vulnerable dependency shipped in a binary takes days to weeks to reach users — App Store review, staged rollout, user update delay — versus a web app where you deploy and every user is on the fix the next time they load the page. This piece covers the risks that actually matter for React Native teams in 2024.
The native module problem nobody measures
Every React Native app has a package.json listing JS dependencies, and many teams audit that list. Very few teams have an equivalent inventory for native modules — the ios/Podfile.lock and android/build.gradle equivalents.
Native modules ship native code that runs with the full permissions of the app process. A malicious or vulnerable native module can access the filesystem, network, keychain, and operating system APIs in ways that JavaScript cannot. When I audit a React Native app, my first artifact is a combined inventory: every package.json dependency that has a native component, plus every CocoaPod, plus every Gradle dependency, with last-publish dates and maintainer info.
The pattern to watch for is abandoned native modules that still work. The RN ecosystem has a long tail of community native modules from 2018-2020 that were never updated for the new architecture, never updated for 64-bit Android, and never updated for anything since. Teams keep them because "they still compile." They should not.
New architecture migration is a security opportunity
React Native's new architecture (Fabric, TurboModules, JSI) shipped as default in 0.76, released in October 2024. The migration forces teams to review their native modules because many community modules need updates to be compatible. This is a security opportunity: as you go module by module checking compatibility, do the same audit for CVEs and maintenance status.
I have seen teams treat the new architecture migration purely as a performance project. It is also a chance to retire five years of accumulated dependencies you do not need.
CodePush and the OTA update attack surface
Microsoft's CodePush lets teams push JavaScript and asset updates to React Native apps without App Store review. It is immensely convenient, and it is a substantial attack surface. Microsoft announced CodePush retirement in March 2024, with the service continuing until end of support; teams are migrating to alternatives like Expo Updates, EAS Update, or self-hosted solutions.
The CodePush security model is that your updates are signed by your private key, and the SDK verifies the signature before applying. If the key is compromised — leaked to a public repo, exposed in CI logs, stored in an HSM with weak access controls — an attacker can push arbitrary JavaScript to every device running your app. The blast radius is immense.
If you are still on CodePush or migrating to an alternative, the key management questions to answer: where is the signing key stored? Who has access to it? How do you rotate it? Is the rotation tested? I have yet to find a team that had satisfying answers to all four.
Expo and its own dependency tree
Expo sits on top of React Native and adds its own managed workflow, including the Expo Go app for development and EAS for builds. Expo SDK 51 released in May 2024 and SDK 52 shipped in November 2024. Each SDK version bundles specific versions of dozens of Expo modules, and upgrading the SDK upgrades all of them atomically.
The good news is that Expo's managed modules are generally well-maintained. The bad news is that staying on an old SDK means accumulated unpatched issues. I have audited apps on Expo SDK 47 (released late 2022) that had skipped four major SDK upgrades. The security-relevant bugs fixed across those upgrades include a path traversal in expo-file-system and an arbitrary file read in expo-image-picker.
If you are on Expo, plan SDK upgrades as part of your normal release cadence, not as a year-long migration project.
The Hermes engine boundary
Hermes is Meta's JavaScript engine for React Native, default in 0.70+. It runs precompiled bytecode, which means a different optimization profile and a different bug surface than V8 or JavaScriptCore. Hermes has had its own advisories; any bug in the engine affects every RN app using it.
The engine is maintained by Meta and tracked alongside the React Native release. Staying on a supported RN version (currently 0.73+, with 0.74 from March 2024 and 0.75 from August 2024 being current) means you get Hermes fixes automatically. Staying on 0.70 or 0.71 means you miss them.
Transitive JS supply chain attacks that hit RN
The node-ipc incident in March 2022 was a reminder that intentionally malicious npm packages target broad audiences, and RN apps are part of that audience. node-ipc was not a direct RN dependency, but it was transitive through several build tooling packages. Any team that ran yarn install during the compromised window on certain regions could have had their environment tampered with.
The more recent polyfill.io compromise in June 2024 (CDN-level, not npm, but equivalent in effect) illustrated that any third-party script source — and React Native apps do load some — becomes an attack surface. Audit every script src equivalent in your RN config and every CDN your app hits.
Permissions: the security feature that gets misconfigured
React Native apps declare native permissions in their Info.plist and AndroidManifest.xml. Community libraries often request more permissions than they need, and those requests show up in your app's permission list whether you actually use the feature or not.
I have seen RN apps requesting location permissions because a map library declared them, even though the app did not use location in any user-facing way. Users decline the permission and then the app behaves strangely. More importantly, a privilege-escalation bug in the native module could escalate using a permission the app never intended to use.
Audit the declared permissions against the features you actually ship. Remove or override any that are not required.
The signing pipeline you probably do not think about
Your iOS and Android signing keys live somewhere. In my audits, those somewheres have included developer laptops (bad), shared 1Password vaults (better, but not great), EAS-managed keystores (good), and HSMs (ideal). A compromised signing key means an attacker can sign updates that are indistinguishable from yours. Treat signing keys as tier-one secrets with full audit logs and rotation procedures.
How Safeguard Helps
Safeguard maintains a combined inventory of your JS dependencies, iOS CocoaPods, and Android Gradle dependencies, so you have one SBOM spanning all three layers of the React Native supply chain. Griffin AI correlates new CVEs against the exact versions shipped in your latest build and flags whether the vulnerable code is reachable given your specific JS bundle. Reachability analysis lets you ignore the hundreds of transitive packages that are installed but never execute at runtime. Policy gates block builds that introduce abandoned native modules or that add permissions without an explicit justification, keeping the mobile supply chain under control even as the app grows.