7 Areas to Review and Harden in Your React Native App
Last reviewed September 14, 2026 against React Native, Apple, Android, and OWASP documentation. Sources are listed at the end.
Security work depends on your threat model: a banking app and a recipe app need different controls. Each item says when it applies and is tagged by effort: Quick (config or audit only), Moderate (code change and app release), or Involved (architecture or backend changes).
Run npm audit (or yarn npm audit on Yarn Berry, yarn audit on Yarn Classic) or our scanner. A match means an installed version falls inside a published advisory's affected range. It does not show that your app uses the vulnerable code.
npm audit fix updates what it can within your version ranges. npm's docs note that some vulnerabilities need manual intervention, and fixes outside your ranges need --force, so test before shipping. npm audit does not cover native CocoaPods or Gradle dependencies.
Anything shipped in the app can be extracted: JavaScript, .env values bundled at build time, Info.plist, strings.xml, and native code. The React Native docs say never to store sensitive API keys in app code, because anyone inspecting the app bundle can read them.
.env files read by react-native-config or similar tools that contain secretsreact-native-config does not hide secrets.
Its README says it doesn't obfuscate or encrypt secrets and warns not to store sensitive keys in .env. It is for configuration such as API endpoints. Moving a secret into it leaves the secret in the shipped app.
Move privileged secrets to a backend you control that calls the third-party service for the app, and give the app short-lived, per-user tokens instead. Identifiers that must ship in the app should be restricted on the provider's side to the minimum permissions they need.
Per-user credentials issued at runtime, such as OAuth access and refresh tokens, do belong on the device, but not in AsyncStorage. The React Native docs describe Async Storage as unencrypted and say not to use it for tokens.
Use storage backed by the iOS Keychain and the Android Keystore, such as react-native-keychain or expo-secure-store. Android's EncryptedSharedPreferences library was deprecated in androidx.security:security-crypto 1.1.0 in favor of using Android Keystore directly, so check what your storage library uses. Keep tokens out of logs and crash reports. Secure storage protects user tokens on the device; it is not a place to hide secrets shipped with the app.
Start with transport security everyone needs. iOS App Transport Security requires HTTPS for URLSession connections by default, and Android 9 and later disable cleartext traffic by default. Check that release builds carry no ATS exceptions or cleartextTrafficPermitted settings meant for local development.
Pin public keys rather than individual certificates, include backup pins with at least one key fully in your control, prefer platform configuration (Android Network Security Config, iOS NSPinnedDomains) or a maintained library, and write down how you'll rotate keys and ship updated pins before any certificate change.
Debug configurations enable developer tooling and often relax network rules to reach the local dev server. Make sure none of that reaches production.
__DEV__ is false and the dev menu is unavailableconsole calls with babel-plugin-transform-remove-console)Local root and jailbreak checks can be bypassed. OWASP's testing guide says root detection "is not very effective by itself," and OWASP MASVS says the absence of these measures is not in itself a vulnerability. They matter for apps whose threat model includes tampering, fraud, or abuse.
Use attestation your server verifies: the Play Integrity API on Android and App Attest on iOS. Apple notes that an app can't reliably check itself, because a compromised app can falsify the results. SafetyNet Attestation was fully turned down in January 2025. Libraries such as jail-monkey can add a local signal, but never gate security decisions on them alone.
The React Native docs say deep links are not secure and should never carry sensitive information. Treat every parameter as untrusted input.
Obfuscation is defense in depth, not a security boundary. OWASP MASVS says it must not be used as a substitute for proper security architecture. R8 shrinks and obfuscates Android Java and Kotlin code, but not your JavaScript bundle. Hermes bytecode can be turned back into readable code with tools listed in the OWASP testing guide.
Bitcode is not an obfuscation control and is obsolete: since Xcode 14, Xcode no longer builds bitcode by default and the App Store no longer accepts bitcode submissions. If an old guide tells you to enable it, skip that step.
Save this checklist for your team. Enter your email and we'll send it over — plus occasional React Native security and dependency updates.
No spam. Unsubscribe any time.
This checklist covers common gaps, not a full assessment. For a manual security audit of your code, configuration, and dependencies, let's talk.
Book a Free Consultation