Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

jso-protector-reactnative

Mobile RASP (Runtime Application Self-Protection) for React Native / Cordova / Ionic apps protected with JavaScript Obfuscator.

JSO's build-time obfuscation makes your shipped JS bundle unreadable. This package adds the runtime half for mobile: a guard that runs inside the app, detects root / jailbreak / Frida / emulator / signature tampering, scores the result, routes it to your SIEM, and fires a response you control.

It is the mobile counterpart to the browser jso-protector/runtime/* modules (third-party-inventory, countermeasures, ai-script-governance) and uses the same beacon envelope shape, so the jso-beacon-slack SIEM adapters forward mobile threats with no adapter change.

Two signal sources

Source Examples Strength
JS-observable (this package, pure JS) Frida globals, Function.prototype.toString tamper, suspicious globals, __DEV__-in-release, instrumentation timing anomaly Weak / evadable — a tripwire, not a guarantee
Native probe (host-wired module) root, jailbreak, Magisk, unc0ver, checkra1n, Dopamine, emulator, Frida/Xposed/Substrate hooks, app-signature mismatch Strong / authoritative — pure JS cannot read the FS or process maps

Honest threat model. JS-only detection raises the cost of casual tampering and catches unsophisticated attaches, but a determined attacker with a native hook can hide most JS-observable signals. The assurance lives in the native probe. Ship both.

Install

npm install https://javascriptobfuscator.com/download/jso-protector-reactnative/jso-protector-reactnative-0.2.0.tgz

This adapter is a versioned direct download and is not published in the npm registry. Pin the URL (or your mirrored copy) in the lockfile.

jso-protector and react-native are optional peer dependencies — the pure RASP engine has zero runtime dependencies and runs anywhere (including Node, for testing).

Build-time (obfuscate the bundle)

Already handled by jso-protector's Metro integration. This package re-exports it for a single entry point:

// metro.config.js
const { withMetro } = require("jso-protector-reactnative");
module.exports = withMetro(baseConfig, { apiKey: process.env.JSO_API_KEY, preset: "balanced" });

Runtime (detect tampering)

import { NativeModules } from "react-native";
import { createMobileGuard } from "jso-protector-reactnative";

const guard = createMobileGuard({
  nativeProbe: () => NativeModules.JsoRasp.probe(),   // see templates/
  beaconUrl:   "https://beacon.example.com/v1/jso/mobile",
  intervalMs:  30000,
  isReleaseBuild: !__DEV__,
  isDev: __DEV__,
  onThreat(report) {
    if (report.verdict === "compromised") { /* gate sensitive flows */ }
  },
});
guard.start();

See examples/App.guard.js for a complete wiring.

Native modules

Pure JS can't read the device. The strong signals come from the bundled self-contained native modules:

  • templates/android/JsoRaspModule.kt
  • templates/android/JsoRaspPackage.kt
  • templates/ios/JsoRasp.swift

The Android probe checks root/Magisk artifacts, su, Frida ports and process maps, Xposed, debugger/emulator state, installer source, and an optional SHA-256 signing-certificate pin. The iOS probe checks jailbreak artifacts and sandbox escape, loaded Frida/Substrate images, tracing, simulator state, enterprise provisioning, and an optional Team ID pin. Both return a result matching the nativeProbeSchema contract:

{ platform, isRooted, isJailbroken, isDebuggable, isEmulator,
  hooksDetected, signatureTampered, unofficialStore, detectedTools[] }

Report shape

{
  "v": 1,
  "kind": "mobile-rasp",
  "verdict": "compromised",
  "score": 110,
  "thresholds": { "suspicious": 30, "compromised": 60 },
  "signals": [
    { "id": "native.rooted", "source": "native", "weight": 60, "detail": "device is rooted" },
    { "id": "native.named-tool", "source": "native", "weight": 50, "detail": "detected tool: Magisk", "tool": "Magisk" }
  ],
  "platform": "android",
  "nativeProbePresent": true
}

verdict crosses to suspicious at score 30 and compromised at 60. Weights are documented in SIGNAL_WEIGHTS and tunable per build.

For compromised devices, respondOnCompromised accepts callback, lock, or lock-and-callback. Lock mode sets globalThis.__jsoMobileLocked so navigation/auth/payment gates can fail closed; onCompromised(report) provides the corresponding application hook.

Testing

npm test

25 Node tests cover the pure-data engine (every signal, the scoring thresholds, malformed input) and the guard orchestration (async probe, probe-throw capture, beacon POST, threat-hook isolation, timer lifecycle). No device required.

Releases

Packages

Contributors

Languages