DEV Community

Cover image for Security Enhancements in React Native Apps
Ajmal Hasan
Ajmal Hasan

Posted on • Edited on

Security Enhancements in React Native Apps

a) JailMonkey (Reference)

JailMonkey is a React Native library built to detect potential security threats on a user’s device. It performs several checks to identify if a device is compromised, either by jailbreaking (iOS) or rooting (Android). This can help apps protect data integrity by detecting security vulnerabilities on the device. Here are the key security features provided by JailMonkey:

  • Identify if a device is jailbroken or rooted on iOS and Android.
  • Detect mocked locations on devices in "developer mode."
  • (Android Only) Check if the app is running on external storage, such as an SD card.

Installation:

yarn add jail-monkey
# or
npm install jail-monkey
Enter fullscreen mode Exit fullscreen mode

Usage:

In your App.js file, add the following code to enable security checks:

import JailMonkey from 'jail-monkey';
import RNExitApp from 'react-native-exit-app';

const checkDeviceSecurity = async () => {
  const isDebuggedMode = await JailMonkey.isDebuggedMode(); // Await the promise
  const isJailBroken =
    JailMonkey.isOnExternalStorage() ||
    JailMonkey.isJailBroken() ||
    JailMonkey.trustFall() ||
    isDebuggedMode ||
    JailMonkey.canMockLocation();

  if (!__DEV__ && isJailBroken) {
    // Display a security warning and exit the app if confirmed
    Alert.alert(
      'Security Warning',
      'This device appears to be compromised. The app will now close for security reasons.',
      [
        {
          text: 'OK',
          onPress: () => RNExitApp.exitApp(),
        },
      ],
      { cancelable: false }
    );
  }
};

useEffect(() => {
  checkDeviceSecurity();
}, []);
Enter fullscreen mode Exit fullscreen mode

For Advance Root Detection Follow:

a) Android Implementation
b) iOS Implementation



b) React Native Code Obfuscation

Introduction

Code obfuscation is a method to make code harder to analyze and reverse engineer. In React Native, this technique can be used to protect intellectual property and enhance app security. We'll cover obfuscation for JavaScript, Android, and iOS code separately.

1. JavaScript Code Obfuscation (Reference)

Using Metro Plugin for JavaScript code obfuscation:

i) Installation:

   npm i -D obfuscator-io-metro-plugin
   # or
   yarn add -D obfuscator-io-metro-plugin
Enter fullscreen mode Exit fullscreen mode

ii) Configuration:

Add the plugin to your metro.config.js file:

   const jsoMetroPlugin = require("obfuscator-io-metro-plugin")(
     {
       compact: false,
       sourceMap: false,
       controlFlowFlattening: true,
       controlFlowFlatteningThreshold: 1,
       numbersToExpressions: true,
       simplify: true,
       stringArrayShuffle: true,
       splitStrings: true,
       stringArrayThreshold: 1,
     },
     {
       runInDev: false,
       logObfuscatedFiles: true,
     }
   );

   module.exports = {
     transformer: {
       getTransformOptions: async () => ({
         transform: {
           experimentalImportSupport: false,
           inlineRequires: false,
         },
       }),
     },
     ...jsoMetroPlugin, // Add this to your previous module configuration
   };
Enter fullscreen mode Exit fullscreen mode

Note: Add *.jso to your .gitignore file.


2. Android Code Obfuscation (Reference)

For Android, we use R8 for code obfuscation:

  • In android/app/build.gradle, enable ProGuard for release builds:
  def enableProguardInReleaseBuilds = true
  .
  .
  .

  buildTypes {
      debug { }
      release {
          debuggable false
          shrinkResources enableProguardInReleaseBuilds
          minifyEnabled enableProguardInReleaseBuilds
          proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
      }
  }
Enter fullscreen mode Exit fullscreen mode
  • In android/app/proguard-rules.pro, keep classes and members required by your app(check in package.json if you using dependent libraries):
 # firebase
  -keep class io.invertase.firebase.** { *; }
  -dontwarn io.invertase.firebase.**

# react-native-config
  -keep class com.awrostamani.BuildConfig { *; }

# react-native-reanimated
  -keep class com.swmansion.reanimated.** { *; }

# react-native
  -keep class com.facebook.react.turbomodule.** { *; }

# react-native-svg
  -keep public class com.horcrux.svg.** {*;}
Enter fullscreen mode Exit fullscreen mode

Note: If your app crashes after enabling ProGuard, check Crashlytics logs or run in release mode to identify any missing keep rules.

Verify the obfuscation by checking your release build with an online tool like Javadecompilers.


3. iOS Code Obfuscation (Reference)

For iOS, there is no built-in library to obfuscate code in React Native. Use third-party tools to apply obfuscation to your Objective-C or Swift code.


c) Enable and Verify APK Signature Scheme v3 and v4:

As of today, Android Studio support v3 and v4 with Android Gradle Plugin 4.2 To enable one or both of these formats in your build, add the following properties to android/app/build.gradle file:

android {
   ...
    signingConfigs {
        ...
        release {
            ...
            enableV3Signing true
            enableV4Signing true
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Ref: https://www.youtube.com/watch?v=1KDJWFi28GI&t=37s


Additional Security Measures

i) Using Secure Storage for Sensitive Data:

Use React Native MMKV or Keychain to store sensitive data securely.

ii) SSL Pinning:

SSL Pinning helps secure data transmission by ensuring that the app only communicates with trusted servers. This protects against man-in-the-middle (MITM) attacks.


By implementing these security measures, you can significantly enhance the integrity and protection of your React Native application against various security threats.

Top comments (0)