Skip to main content

Command Palette

Search for a command to run...

Essential Security Configurations for Expo-Based Mobile Applications

Fixing Security Vulnerabilities in an Expo Mobile Application: Findings, Priorities, and Solutions

Updated
β€’6 min read
Essential Security Configurations for Expo-Based Mobile Applications
V

Hey there! I'm Vimal Negi, a passionate and self-driven Full-Stack Developer and Final-Year Engineering Student. I love building interactive web applications and solving real-world problems using technologies like React, Node.js, Express, MongoDB, and Tailwind CSS.

Vulnerability

Deprecated React Native Version in Use

Priority

High

Impact

Using an outdated React Native version may expose the application to known security vulnerabilities, bugs, and compatibility issues that have already been addressed in newer releases.

Solution

For applications built with Expo, upgrading React Native directly is generally not recommended because Expo SDK versions are tightly coupled with specific React Native versions.

Instead, the recommended approach is:

  1. Upgrade the Expo SDK to the latest supported version -: Upgrade the Expo SDK to the latest supported version. When upgrading from an older SDK, it is recommended to upgrade one SDK version at a time rather than jumping multiple major versions. For example, if the project is on SDK 50, upgrade to SDK 51 first, then SDK 52, and so on until the target version is reached. This helps identify compatibility issues early and makes troubleshooting easier. npx expo install expo@^51.0.0

  2. Run the following command -:

npx expo fix

  1. Allow Expo to automatically update project dependencies to versions compatible with the selected Expo SDK.

This approach ensures that React Native, Expo modules, and other dependencies remain compatible with each other, reducing the risk of build failures and runtime issues.

Remediation Performed

The application's Expo SDK was upgraded, and npx expo fix was executed to align all dependencies with the SDK's supported versions. This automatically updated React Native and related packages to compatible versions.

Vulnerability

Application Vulnerable to SSL Pinning Bypass

Priority

High

Solution

The application was enhanced with additional runtime integrity checks using the JailMonkey library. The following controls were implemented:

  • Root/Jailbreak detection

  • Runtime hook detection

  • Developer mode detection

  • Mock location detection

  • Periodic integrity validation during application execution

If any device tampering or runtime manipulation is detected, the application terminates execution to reduce the risk of SSL pinning bypass through instrumentation frameworks such as Frida or similar dynamic analysis tools.

import { useEffect, useState } from 'react';
import { ExpoRoot } from 'expo-router';
import { BackHandler, View, ActivityIndicator } from 'react-native';
import JailMonkey from 'jail-monkey'; // πŸ›‘οΈ Anti-Bypass Framework

const context = require.context('./src/app');

export default function App() {
  const [isDeviceSafe, setIsDeviceSafe] = useState<boolean | null>(null);

  useEffect(() => {
    
    async function checkDeviceSecurity() {
      try {
        const isJailBroken = JailMonkey.isJailBroken();
        const isHooked = JailMonkey.hookDetected();
        const isMocked = JailMonkey.canMockLocation();
       
        const isDevelopmentMode = await JailMonkey.isDevelopmentSettingsMode();

        if (isJailBroken || isHooked || isMocked || isDevelopmentMode) {
          console.warn("🚨 Security integrity breach! System compromised.");
          BackHandler.exitApp();
          return false;
        }
        setIsDeviceSafe(true);
        return true;
      } catch (error) {
        BackHandler.exitApp();
        return false;
      }
    }

    checkDeviceSecurity();

    const securityInterval = setInterval(() => {
      checkDeviceSecurity();
    }, 4000);


    return () => clearInterval(securityInterval);
  }, []);

  if (isDeviceSafe === null) {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#ffffff' }}>
        <ActivityIndicator size="small" color="#000000" />
      </View>
    );
  }


  return <ExpoRoot context={context} />;
}

Vulnerability

Application Vulnerable to Janus (CVE-2017-13156)

Priority

High

Solution

The application was rebuilt using modern Android SDK and build tool versions and is distributed through the Google Play Store, which applies secure app signing mechanisms that are not affected by the Janus vulnerability.

{
  "compileSdkVersion": 36,
  "targetSdkVersion": 36,
  "minSdkVersion": 24
}

Vulnerability

Cleartext Traffic Enabled

Priority

High

Solution

Disabled cleartext (HTTP) network traffic and enforced encrypted communication channels by configuring the Android application to allow only secure HTTPS connections.

{
  "android": {
    "usesCleartextTraffic": false
  }
}

Vulnerability

Insecure Android Backup Configuration Enabled

Priority

Medium / High (depending on the auditor's classification)

Solution

Android backups were disabled to prevent application data from being included in device backups. This reduces the risk of sensitive information being extracted from backup files and restored on unauthorized devices.

Initially, the following configuration was added to app.json:

{
  "android": {
    "allowBackup": false
  }
}

However, this setting was not reflected in the generated Android manifest during the build process. Therefore, the backup configuration was explicitly disabled in AndroidManifest.xml.

Remediation Performed

The <application> tag in AndroidManifest.xml was updated as follows:

<application
    android:name=".MainApplication"
    android:label="@string/app_name"
    android:icon="@mipmap/ic_launcher"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:allowBackup="false"
    android:theme="@style/AppTheme"
    android:supportsRtl="true"
    android:enableOnBackInvokedCallback="false"
    android:fullBackupContent="@xml/secure_store_backup_rules"
    android:dataExtractionRules="@xml/secure_store_data_extraction_rules"
    android:usesCleartextTraffic="false">

Vulnerability

Insecure Permissions Requested

Priority

Medium

Solution

The application's requested permissions were reviewed to identify permissions that were not required for business functionality. Unnecessary permissions increase the application's attack surface and may expose sensitive device resources without a valid use case.

All permissions should be evaluated with the development team to determine whether they are genuinely required. Permissions that are not required should be removed from the application manifest.

Remediation Performed

Initially, unnecessary permissions were blocked through the Expo configuration:

{
  "android": {
    "blockedPermissions": [
      "android.permission.READ_EXTERNAL_STORAGE",
      "android.permission.WRITE_EXTERNAL_STORAGE"
    ]
  }
}

If the permissions are still present in the generated manifest after building the application, they can be explicitly removed from AndroidManifest.xml using tools:node="remove".

<uses-permission
    android:name="android.permission.READ_EXTERNAL_STORAGE"
    tools:node="remove" />

<uses-permission
    android:name="android.permission.RECORD_AUDIO"
    tools:node="remove" />

<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    tools:node="remove" />

Vulnerability

Insecure Clipboard Usage

Priority

Medium

Solution

Sensitive input fields were configured to prevent users from copying, cutting, pasting, or automatically selecting sensitive information. This reduces the risk of credentials being exposed through the device clipboard, which may be accessible by other applications.

Remediation Performed

The login form input fields were updated with the following security controls:

<TextInput
  style={styles.input}
  placeholder="User ID or Email"
  value={userId}
  onChangeText={setUserId}
  autoCapitalize="none"
  keyboardType="email-address"
  contextMenuHidden={true}
  selectTextOnFocus={false}
/>

<TextInput
  style={styles.input}
  placeholder="Password"
  value={password}
  onChangeText={setPassword}
  secureTextEntry={true}
  contextMenuHidden={true}
  selectTextOnFocus={false}
/>

Security Controls Applied

  • secureTextEntry={true} hides password characters from on-screen display.

  • contextMenuHidden={true} disables the copy, cut, and paste context menu.

  • selectTextOnFocus={false} prevents automatic text selection when the field gains focus.

Vulnerability

Application Source Code is Not Obfuscated

Priority

Medium

Solution

Code obfuscation was enabled for Android release builds to make reverse engineering and static analysis more difficult. Obfuscation renames classes, methods, and variables while also removing unused code, thereby increasing the effort required to understand the application's internal implementation.

Remediation Performed

The following configuration was added to the Expo build properties:

{
  "android": {
    "enableProguardInReleaseBuilds": true
  }
}