No More Seat Costs: Semaphore Plans Just Got Better!

    4 Oct 2023 · Software Engineering

    Ready to Release? Securing Your React Native Apps

    12 min read
    Contents

    React Native popularity and adoption is ticking up every day, and it is used to build many enterprise applications. As it is gaining more traction, more vulnerabilities are being discovered and reported. This means that it is crucial to keep the security of React Native apps in mind while building them. Because of its open-source background, RN apps are more prone to security vulnerabilities. This means that more vigilance is needed to keep them secure.

    Since most of the logic for React Native apps is written in JS, the coverage or threat area is much larger than that of native apps. So, in essence, we have to ensure the security of both the native code and the JS code. Just like any other frontend app, the code of the app is shipped to devices for execution, which makes it inherently vulnerable to getting tampered with.

    This article will look at some of the most common security threats for React Native apps and some of the tools and techniques that can be used to secure against them.

    Tools & Tricks

    Let’s look at some super valuable tools and techniques to make your React Native apps more secure. We will cover the areas of network security, data security, static analysis, dependency security, platform security, and more.

    Secure Network Communication – SSL Pinning

    As much as 35% of attacks in 2019 were related to attempts at exploitation using Man in the Middle attacks. For mobile apps communicating with servers, it is necessary to ensure that communication is secure and not tampered with. SSL pinning is a technique that allows you to verify the identity of the server you are communicating with, helping you avoid MITM attacks.

    Apps using HTTPS depend on CA and DNS to verify the server’s identity. A malicious actor can bypass this by setting up an unsafe certificate on the client’s devices and making all communication between the client and the server insecure.

    SSL pinning allows you to verify the server’s identity by verifying the server’s certificate; this is done by verifying the server’s certificate fingerprint. SSL pinning will ensure that the communication is secure and has not been tampered with.

    Here are a couple of tools for SSL pinning:

    • React Native SSL Pinning: This enables SSL pinning & public key pinning using OkHttp3 on Android & AFNetworking on iOS. To leverage the library, we override React Native’s fetch with import {fetch} from 'react-native-ssl-pinning'. It also supports multipart forms. Important note: you have to implement error handling for certificate expiry and might require an app update to update certificates.
    • React Native Pinch: an HTTP client that supports SSL pinning for React Native. It also wraps the fetch method.

    Securing Stored Data

    Today’s apps rely not only on network data, they also store data locally on the device. This data can be sensitive and should be protected. Another critical aspect of security is to ensure that all data stored on the device is secure; this includes data stored in the app’s local storage, database, cache, etc. It is crucial to ensure that the data stored on the device is not accessible to other apps or users.

    Fortunately, iOS and Android provide tools to secure data stored on devices using Keychain and Keystore, respectively. Here are some of the RN wrappers for these tools:

    • React Native MMKV is the fastest Key-Value storage for React Native apps by far; it relies on the native security of app files and also provides encryption. It is a wrapper around MMKV.
    • React Native Encrypted Storage is a module that helps secure data by providing a wrapper around Android’s EncryptedSharedPreferences and iOS’ Keychain. It comes complete with support for TypeScript.
    • RNSecureStorage is another option that uses Keychain for secure storage with iOS. While for Android, it uses secure-preferences for below API 23  and Android Keystore for above API 23. It also allows you to make data accessible only after specific user actions on the device, like, when the passcode is set, when a device is unlocked, etc.

    However, it is essential to note that these tools are not a silver bullet. They are not a replacement for proper data encryption. They are just a way to secure data stored on the device. For an added security layer; It is better to encrypt data before storing it on the device. Or better yet, don’t store data on the device in the first place.

    Obfuscation of JS Code

    Obfuscation is a technique that makes the code harder to read and understand. Obfuscation makes it harder for attackers to understand code and exploit it. For React Native apps, obfuscation of JS code is more important than obfuscation of native code, as most of the app logic resides in JS. General obfuscation of JS code done by default modifiers or Hermes conversion of JS to bytecode is not enough. It is essential to use a tool that can obfuscate the code in a way that is harder to understand and exploit.

    Here are some of the tools for obfuscation:

    • Jscrambler protects your JavaScript with polymorphic obfuscation, code locks, and self-defensive capabilities to prevent code theft, abuse, and tampering.
    • JSDefender provides JS obfuscation with control-flow flattening, tamper detection, and other in-app protection transforms.

    Protection from SQL Injection

    SQL injection is a code injection technique that can destroy your database. It is also one of the most common web hacking techniques. Be it the apps using the local database or API calls to remote servers, SQL injection is a threat to both. It is essential to protect your app from SQL injection attacks. All user input should be appropriately validated and sanitized before being used outside any UI scope. Sanitization will ensure that the user input is not malicious for the app.

    Here are some tools for protection from SQL injection attacks:

    • Formik is a popular form library for React Native apps. It provides a way to validate and sanitize user input. It also provides a way to validate user input against a schema. It helps validate and sanitize user input before using it in any SQL query.
    • Validator.js is the library to validate and sanitize strings in your app; all user inputs should pass through this library before being used anywhere in the app.

    Here is a more detailed guide on input validation to protect your app from SQL injection.

    Segregation of Authenticated & Public Parts

    In most applications, some parts are accessible to everyone, and components are accessible only to authenticated users or users with a specific role. It is essential to keep these parts of the application separate. Segregation will help you to keep your application secure. For React Native apps, this can mostly be done at the Javascript level with multi routers and multi bundles.

    • React Navigation allows you to create multiple routers in your application, So the authenticated and public parts of your application can be separated. Multiple routers will enable you to load authenticated parts of your Javascript only when the user is authenticated.
    • Re.pack can be a helpful tool for creating multiple bundles in your application. It enables you to deliver authenticated features of your application remotely.

    Static Application Security Testing (SAST)

    Static Application Security Testing (SAST) is a type of application security testing that analyzes application source code, byte code, and binaries for software vulnerabilities. SAST tools analyze an application without actually running it, and can find vulnerabilities that are difficult to see with dynamic testing. SAST tools are also high-speed and can scan code in a CI/CD pipeline.

    Here are some of popular tools for SAST:

    Checking Dependencies for Vulnerabilities

    Usually, React Native apps use a lot of third-party libraries. It is essential to regularly check these libraries for vulnerabilities. Relying on a library that has a vulnerability can be a security risk. To keep our apps secure, we should regularly check our dependencies for vulnerabilities. It is important to make a dependency check part of the CI/CD pipeline for every PR or commit, so that you can be sure that the app is not using any vulnerable libraries.

    Here are some tools that can help you check your dependencies for vulnerabilities:

    Jailbreak/Rooted Device Detection

    Jailbroken or Rooted devices, as well as emulators, sometimes bypass security measures provided by the OS. Attackers can use such devices to access sensitive data and perform malicious actions. It is essential to detect jailbroken and rooted devices and prevent them from accessing your app. 

    Here is a good tool to detect jailbroken and rooted devices:

    • Jailmonkey JailMonkey allows you to identify if a phone has been jailbroken or rooted for iOS/Android. It also lets you identify if the app is running in an emulator.

    Checking for App Tampering

    App tampering can be done by modifying the app binary or by modifying the app data. It is crucial to detect app tampering and prevent the app from running if it has been tampered with. This is especially important for apps handling sensitive user data or financial transactions, as it must be ensured that all transactions are triggered by a genuine app running on a genuine device.

    Here are some of the tools that can be used to detect app tampering:

    • Google Play Integrity provides an attestation API to check whether your server is interacting with an unmodified binary, for paid apps it ensures that the current user account is licensed to use the application, and if the app is running on a genuine android device. Unfortunately, a React Native wrapper for Play integrity isn’t yet available.
    • React Native SafetyNet is a wrapper over Google’s SafetyNet API. The SafetyNet Attestation API is an anti-abuse API that allows app developers to assess an Android device that their app is running on. The API should be used as a part of your abuse detection system to help determine whether your servers are interacting with the genuine app running on a genuine Android device. Important note: Google has stated that they will discontinue SafetyNet in favor of Play Integrity.

    Getting Deep-Linking Right

    Deep-linking is a way to open a specific screen in your app from a URL. It is essential to get deep-linking right in order to prevent phishing attacks. It is crucial to validate the URL before opening the screen. It is also necessary to make sure that private URLs are not accessible to everyone and, above all, that URLs are pruned before the app processes them.

    For apps using third-party libraries with deep linking, it is vital to ensure that the libraries are not vulnerable to phishing attacks.

    Platform Security (Android/iOS)

    React Native apps work on both Android and iOS, so it is vital to keep the security of both platforms in mind while building your app. Any tools or techniques available to secure native apps are equally relevant to React Native apps.

    Here are some Guardsquare tools to secure your app on both platforms:

    • DexGuard (Android) offers several security features for Android apps. It protects your app from reverse engineering, tampering, and other attacks. It can also obfuscate your code and save your app from decompilation.
    • iXGuard (iOS) iXGuard protects iOS applications. It secures iOS apps and SDKs using multiple layers of code hardening and runtime application self-protection (RASP).

    App Distribution & Signing

    It’s also essential to ensure that the application is signed correctly and distributed through official channels to prevent malicious actors from distributing tampered versions of the application. For large-scale apps developed by multiple teams, it is important to have a proper process in place to ensure that the application is properly signed and distributed. CI/CD pipelines should be used to automate signing and distribution of the application.

    • Fastlane match is a tool that can be used to manage certificates and provisioning profiles. It can create a private repository for certificates and provisioning profiles, and ensure that certificates and provisioning profiles are not leaked to the public.

    Bring Security to CI/CD

    In addition to these security considerations, it’s important to keep in mind the best practices for securing a CI/CD pipeline, such as implementing secure authentication and access controls and regularly monitoring for and addressing any security threats or vulnerabilities. Here are some security actions that should be implemented in your CI/CD pipeline:

    For every PR before merging:

    • SAST checks
    • Checking for vulnerable dependencies
    • Ensure that storage is not used without encryption
    • Running automated tests to verify that authenticated parts of the app are accessible only with authentication

    For release builds:

    • Restrict access to prod SSL certs by injecting them into the app at build time
    • Checking for deep-linking vulnerabilities before releasing the app
    • Signing the app with release certificates from the pipeline to prevent them from being leaked
    • Testing the hardening of release builds on jailbroken and rooted devices before releasing the app

    Conclusion

    React Native is an excellent framework for building cross-platform apps, but it is essential to keep security in mind. Whether you’re working with financial or personal data, it is crucial to keep your app secure. Security is an ongoing marathon, and we must keep ourselves up-to-date with the latest security threats and vulnerabilities.

    One thought on “Ready to Release? Securing Your React Native Apps

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    Avatar
    Writen by:
    Zain Sajjad is the Head of Frontend Development at Peekaboo Guru, passionate about writing scalable products using JavaScript, WebAssembly & ML on edge.
    Avatar
    Reviewed by:
    I picked up most of my soft/hardware troubleshooting skills in the US Army. A decade of Java development drove me to operations, scaling infrastructure to cope with the thundering herd. Engineering coach and CTO of Teleclinic.