Obfuscate codehelps.- JS Bundles - https://github.com/vesselsoft/metro-minify-obfuscator
- https://github.com/MichaelXF/js-confuser - Adding this here as a note, because it could end up better than the
javascript-obfuscator, but it might require aRN / Metroimplementation with a workingsourcemapsupport.
- https://github.com/MichaelXF/js-confuser - Adding this here as a note, because it could end up better than the
- Android -
Proguard/R8 - iOS - I dont know any that is open-source and works. Before deprecation,
BITCODEwas used. However there is a commercial one callediXGuard. - JS are still easier to
decompile/deobfuscatethannative, so ideally, if you can, the more you implement in thenativeside, the better. That's why one of the recommendations below is to use a single point of implementation, withRustorC++.
- JS Bundles - https://github.com/vesselsoft/metro-minify-obfuscator
Jailbreak/rooted/emulatorchecks, close app if detected.- Runtime App Self Protection
(RASP) - https://github.com/bamlab/react-native-app-security - Mix of checks, left it here, but other standalone options are likely better.
- Require
app updates, as to not support older versions. Having checks in place. OTAcould help provide fasterhotfixesin case some security issue are discovered or bad impl are done. It's on theJSside only.- https://github.com/gronxb/hot-updater - This tool seem to be working to be more than that.
Integrity checks- It may havequotasfor verifications. I suppose it could becached, once per install.- https://github.com/pagopa/io-react-native-integrity
- https://rnfirebase.io/app-check/usage
- https://github.com/niteshbalusu11/react-native-secure-enclave-operations
- Alternatively you can generate
SHA512 checksumsyourself manually through the CI for bothnativeandjsbundles. But it takes more work. And probably would require some other implementationnativelyand injs.
- Disable any sort of
debugging. - To store
auth tokensand others.- https://github.com/oblador/react-native-keychain
- If some things are not possible with
keychain, there is https://github.com/mrousavy/react-native-mmkv as alternative if used withencryption.
- Do all things in the
backend. TheApp / Webshould be only for displaying data and taking action on it for the most part.- You can make use of
Paseto(auth token) in the backend. - By using
Paseto, you can have two things, a less vulnerable alternative toJWTfor authentication, and verification of the payload with it'sprivate/publickey, similarly asHMAC Signatureintent, helps ensure the integrity of the data being transported. - Make use of
refresh tokenandaccess tokenpattern, whererefresh tokenonly serves to refresh theaccess tokenwhich should have duration of minutes, andaccess tokento request content only. - Use
argon2for password hashing. - Never return
databaseerror messages ordatathat may be sensitive, in errors fromAPIresponses, that should belogged/reportedto the developer, to befixed. Thefrontendshould only know that an error happened and the admin or developer are aware, butvalidationerror messages can be returned. - You can opt to use multiple login types (
MFA - Multi Factor Auth), nopasswordmight be safer, so there isOTPauth as option, be throughemail,SMSor some othermessaging toolto receive the code.2FAcan be an additional security option.HOTPorTOTP.
- You can make use of
Device Binding, you could send specific information from the smartphone like a combined stringuniqueDeviceId+deviceManufacturer+modeland tie theauth tokento it. That way, it cannot be used in another device.- You can session limit with device binding. Like one device at the time or more.
SSL Pinning- though there isPublic Key Pinning, and it might be a better option.- https://github.com/frw/react-native-ssl-public-key-pinning
- https://github.com/huytdps13400/react-native-ssl-manager
- There are things that point to being easy to
bypass pinning, though with checks and actions in place forjailbreak, rooted, emulators and hooks(but not only), can help reduce or even completely prevent the possibility of this.
Biometricscould help make it more difficult.- Even
hardware keys/passkeys, but this would be something optional like2FAis in some cases. - For
encryptionwork, I would say to do in thebackend, but if not possible. - No
loggingon release.- https://babeljs.io/docs/babel-plugin-transform-remove-console
- This means no
consolebased nor any other logginglibusage.
Input Sanitization / Validation- This should be prioritized in the backend, but it's fine on app too.- https://github.com/colinhacks/zod
- https://github.com/cure53/DOMPurify for
HTMLin case you use Webview. But preferably, opt-out.
- Keep
RNanddependenciesupdated.- Use only the best options (most used) available and keep to a minimum.
- Have something in place to auto-upgrade the packages and do code upgrades if major changes are needed.
- Disable
recording/screenshotin the app. - Have
app signatureverification set.- While the firebase options above is a similar way to check, it's not the same.
- Currently, this might require some manual work on the native side. As well as managing generated certs.
- Always combine with backend checks where possible, not only on the client-side, since that can be bypassed.
- Never use
deep linksfor sensitive data. - No sensitive
env varsin the frontend/app.- But there is a safer option than
react-native-configandreact-native-dotenv, that can helpenv varsthat are not possible to have the setup in thebackend- https://github.com/numandev1/react-native-keys- Currently
react-native-keysstill has ways to go to be free of vulnerabilities. But at this point it's the safer option.
- Currently
- But there is a safer option than
- Have
CIdependencyvulnerabilitiesverification checks withsnykor some other tool. - Develop
nativefunctionality in a single point rather than inJava/KotlinandObjC/Swift, this way it can help prevent bugs and even security issues.- I would recommend in
Rust - But, if you prefer
C++, there is https://github.com/mrousavy/nitro as alternative.
- I would recommend in
- OWASP
Lint/Typesare recommendedLintare recommended due to it's checks which can help prevent security issues.Typesare recommended withTypescript, with proper configuration, you can enforce additional good practices, therefore having less bugs, so leading to less security issues.- All should be enforced in both
devenvironment andCI.
Testsare recommended at least in crucial parts of the app, and backend.- Good tests will check for things that should not be possible, so, it can help prevent security issues.
- https://jestjs.io/ -
Jestare still the recommended choice inReact Nativedue to better support with other libraries. Other equivalent libraries are not that well supported or not at all. - https://callstack.github.io/react-native-testing-library/ -
ComponentandIntegrationtests. - https://wix.github.io/Detox/ for
E2Etests.
- For the backend, if starting something new, I would recommend
RustorDenoJSwhich are based in rust, both are likely to have less vulnerabilities. Just my opinion though.- Your data is a
secureas you made yourbackendto be. In all ends of it.- OS always keep to a minimum in
packages, always updated. - There are
hardenedkernels and many things that can be done to increase security in the OS part. - API preferably
containerized. - Everything
isolatedandharderto access, withstrictconfigurations, and so on. And not just what you or someone else know, but researched and updatedconfigto latest and safest approaches. - Ideally ALL should be
automated, to have predictable actions done to theserver, as to prevent things done by someone, where someone else would not know about it. Everythingstored in a repo/commited, of course.
- OS always keep to a minimum in
- If not starting new, and there is a legacy system that requires scaling and need a rewrite,
Rustcan be a great alternative too.
- Your data is a
- There are other things, that can also help, but those are more specific things like configurations, those you should search by yourself.
- One example being related to android
apk signing, onlyv4being free of known vulnerabilities. - Fstack Protector
- In ios (xcode), select the target in the
Targetssection, then click theBuild Settingstab, make sure that the-fstack-protector-alloption is selected in theOther C Flagssection and thatPosition Independent Executables (PIE)support is enabled. - In android,
android/build.gradlein one of the build configurations, make sure thatcmake > cppFlagshas-fstack-protector-allas one of it's setting.
- In ios (xcode), select the target in the
- One example being related to android
Like everything else, it's your responsibility to confirm whether your implementation are working by adding checks / doing security analysis.
Some additionals suggestion by Gemini 2.5 - https://pastebin.com/raw/uyaeKjsr