React Native App Security (Part 2): Protecting Your App from Rooted and Jailbroken Devices
Detecting Rooted and Jailbroken Devices Using JailMonkey
React Native App Security (Part 2): Protecting Your App from Rooted and Jailbroken Devices

Detecting Rooted and Jailbroken Devices Using JailMonkey
In part 1, we explored why mobile apps are attractive targets and how attackers analyze React Native applications.
Now let’s focus on one of the most common high-risk environments your app can run in:
Rooted Android devices and jailbroken iPhones.
If an attacker controls the device itself, many operating system protections no longer apply. Runtime hooking becomes easier, private storage can be inspected, and security checks can be bypassed.
This is where device integrity checks become important.
We’ll look at:
- What rooted and jailbroken devices are
- Why they increase security risk
- How attackers exploit them
- How to detect them in a React Native app using JailMonkey
Why Rooted and Jailbroken Devices Matter
Mobile operating systems rely on strict security models.
Both Android and iOS isolate apps using sandboxing, which prevents applications from accessing each other’s data or modifying system components.
Rooting or jailbreaking removes many of these restrictions.
When a device is compromised, attackers gain much deeper access to the system.
This allows them to:
- Inspect private application storage
- Intercept runtime function calls
- Modify application behavior
- Install instrumentation tools
- Bypass security mechanisms
For attackers analysing mobile apps, rooted or jailbroken devices are the preferred environment.
What Is a Rooted Android Device?
Rooting gives a user administrative access to the Android operating system.
With root privileges, attackers can:
- Modify system files
- Install custom frameworks
- Bypass sandbox restrictions
- Access protected directories
Common tools used on rooted devices include:
- Magisk
- Xposed Framework
- Frida
- Custom ROMs
These tools allow attackers to inspect and modify application behavior at runtime.
What Is a Jailbroken iPhone?
Jailbreaking removes Apple’s restrictions on the iOS operating system.
It allows users to install software that Apple normally blocks.
Once jailbroken, attackers can:
- Install un-authorised applications
- Access application containers
- Inspect runtime memory
- Modify app behaviour
Popular jailbreak ecosystems include tools such as:
Just like on rooted Android devices, these tools make dynamic analysis much easier.
Why Compromised Devices Are Dangerous for Your App
When an attacker controls the device, they can perform several powerful attacks.
Let’s look at a few examples.
1. Runtime Hooking
Instrumentation frameworks like Frida allow attackers to intercept and modify function calls while the app is running.
For example, an attacker could hook a function that checks whether a user has access to a premium feature.
isUserPremium() → return true
Even if the user never purchased the feature, the application might behave as if they did.
2. Local Data Extraction
Sensitive data stored on the device can also become accessible.
Examples include:
- Authentication tokens
- Cached API responses
- Locally stored databases
- Configuration files
If sensitive data is not stored securely, attackers may be able to extract it directly.
3. Bypassing Security Protections
Many security protections become easier to bypass on rooted devices.
Attackers can:
- Disable security checks
- Bypass SSL pinning
- Modify runtime values
- Intercept API requests
This is why security-sensitive applications such as banking apps often restrict functionality on compromised devices.
Detecting Compromised Devices
To reduce risk, many mobile apps implement device integrity checks.
These checks attempt to determine whether the device has been rooted or jailbroken.
Common detection techniques include:
1. File System Checks
Checking for files commonly present on rooted devices.
Examples:
/system/bin/su
/system/xbin/su
/system/app/Superuser.apk
2. Suspicious Application Detection
Looking for apps commonly installed during rooting or jailbreaking.
Examples include:
- Magisk
- SuperSU
- BusyBox
3. Writable System Directories
Some root detection systems check whether protected system directories can be modified.
Normally these directories should be read-only.
4. Debugging and Emulator Checks
Some tools also detect debugging environments or emulators commonly used during security testing.
Implementing Root Detection in React Native
Instead of implementing these checks manually, developers often use libraries that combine multiple detection strategies.
One of the most commonly used libraries in React Native applications is JailMonkey.
JailMonkey provides a simple API for detecting compromised environments on both Android and iOS.
1. Installing JailMonkey
Install the package using npm or yarn.
npm install jail-monkey
or
yarn add jail-monkey
After installing, rebuild your project so the native module is properly linked.
2. Basic Root Detection Example
Once installed, detecting a compromised device is straightforward.
import JailMonkey from "jail-monkey";
const compromised = JailMonkey.isJailBroken();
if (compromised) {
console.warn("Device integrity compromised");
}
This method checks whether the device appears to be rooted or jailbroken.
3. Additional Device Integrity Checks
JailMonkey also provides several additional checks that can help identify suspicious environments.
For example:
JailMonkey.isDebuggedMode();
JailMonkey.isOnExternalStorage();
JailMonkey.canMockLocation();
These checks can help detect:
- Debugging sessions
- Apps running from external storage
- Location spoofing
Using multiple checks together improves detection accuracy.
4. Code Example
A clean pattern is to encapsulate all checks in a single useDeviceSecurity hook that returns a boolean. Everything in the app keys off that one value.
import { useEffect, useState } from "react";
import JailMonkey from "jail-monkey";
const useDeviceSecurity = (): boolean => {
const [isDeviceSecure, setIsDeviceSecure] = useState(true);
useEffect(() => {
if (__DEV__) return; // skip checks in development
const checkSecurity = async () => {
const rootedDetection = JailMonkey.androidRootedDetectionMethods;
const isRootedByRootBeer = rootedDetection?.rootBeer
? Object.values(rootedDetection.rootBeer).some(Boolean)
: false;
const isCompromised =
JailMonkey.isJailBroken() ||
JailMonkey.trustFall() ||
JailMonkey.hookDetected() ||
JailMonkey.AdbEnabled?.() ||
(await JailMonkey.isDebuggedMode?.()) ||
isRootedByRootBeer ||
rootedDetection?.jailMonkey;
setIsDeviceSecure(!isCompromised);
};
checkSecurity();
}, []);
return isDeviceSecure;
};
A few points worth noting:
- DEV bypass: Checks are skipped in development so you’re never blocked on a simulator.
- trustFall(): A convenience aggregator covering several checks in one call.
- androidRootedDetectionMethods: Gives access to both RootBeer’s granular flags and JailMonkey’s own detector — checking both improves Android coverage.
- Optional chaining (?.): Some APIs are Android-only; the optional chaining prevents crashes on iOS.
At startup, consume the hook and route accordingly:
const isDeviceSecure = useDeviceSecurity();
// In your startup navigation logic:
if (!isDeviceSecure && !__DEV__) navigate('ApplicationUnavailable');
How Should Apps Respond?
Detecting a rooted device is only the first step.
Your application also needs to decide how it should respond.
Different applications choose different strategies depending on risk level.
1. Display a Security Warning
Some applications simply inform the user that the device appears to be compromised.
Example:
This device appears to be rooted.
Some features may be unavailable for security reasons.
2. Restrict High-Risk Features
Security-sensitive functionality can be disabled.
Examples include:
- Payments or Financial Transfers
- Password changes
- Account recovery
This approach reduces the impact of potential attacks.
3. Flag the Device on the Backend
The app can send a signal to backend services indicating that the device appears compromised.
Example:
device_integrity = compromised
Backend systems can then apply additional monitoring or fraud checks.
4. Block Access Entirely
Some high-security applications, particularly in banking and fintech, refuse to run on rooted or jailbroken devices.
This approach offers stronger protection but may affect user experience.
Limitations of Root Detection
Root detection improves security, but it is not foolproof.
Attackers can sometimes bypass these checks using techniques such as:
- Magisk Hide
- Root cloaking modules
- Patched system images
- Modified libraries
Because of this, root detection should be treated as one layer in a broader security strategy.
It helps identify high-risk environments, but it cannot stop determined attackers on its own.
Combining Device Integrity with Other Security Layers
The most effective mobile security strategy combines multiple protections.
Device integrity checks work best when combined with:
- Secure storage for sensitive data
- Backend request verification
- SSL pinning
- Fraud detection systems
Together, these layers significantly increase the effort required to attack your application.
메타데이터
- post_id
- a0d7e133aaa3
- slug
- react-native-app-security-part-2-protecting-your-app-from-rooted-and-jailbroken-devices-a0d7e133aaa3
- url
- https://medium.com/@rosingh3342/react-native-app-security-part-2-protecting-your-app-from-rooted-and-jailbroken-devices-a0d7e133aaa3
- canonical_url
- https://medium.com/@rosingh3342/react-native-app-security-part-2-protecting-your-app-from-rooted-and-jailbroken-devices-a0d7e133aaa3
- author_url
- https://medium.com/@rosingh3342
- status
- ok
- fetched_at
- 2026-07-13 15:35:31