SDK
Mobile
Mobile Threat SDK

Mobile Threat SDK

Measures what device a transaction in your mobile app is happening on, at that moment: is the device jailbroken, is it an emulator, is someone watching the screen remotely, has the app been repackaged. It turns the answer into a typed verdict.

There are two bridge packages, and both expose the same surface.

PlatformPackageVersion
Flutterlunixi_mobile_threat_sdk0.1.0
React Native@lunixi/mobile-threat-react-native0.1.0

A bridge package is not the collector. The Dart/TypeScript layer orchestrates; the actual threat and posture collectors live in the native modules (Android and iOS). That is deliberate — if the security measurement ran in the JavaScript layer, whoever compromised that layer would defeat it too.

Verdict values

allow · step_up · review · deny

step_up means you should raise the transaction to additional verification — the device is not bad enough to decline, but not clean enough to let through as is.

The basic flow

import { LunixiMobileThreat } from '@lunixi/mobile-threat-react-native';
 
// Collect telemetry and evaluate in one call
const verdict = await LunixiMobileThreat.collectAndEvaluate(session);
 
if (verdict.status === 'deny') {
  // stop the transaction
} else if (verdict.status === 'step_up') {
  // ask for additional verification
}

You can call collectTelemetry and evaluateMobileThreat separately; collectAndEvaluate is the convenience that combines them.

Session context

An evaluation requires a session context:

FieldRequiredMeaning
merchantId · sessionIdyesTenant and session
subjectType · subjectIdyesWhat you are evaluating (customer, device…)
sdkVersionyesThe bridge package's version
traceId · customerId · paymentId · entryPointnoCorrelation and context

The trusted action token

Used to cryptographically bind a high-risk action (a transfer, adding a beneficiary) to the device.

const token = await LunixiMobileThreat.requestTrustedActionToken({
  actionType: 'transfer',
  sessionId,
  challengeNonce,
  amount: '250000',
  currency: 'TRY',
  beneficiaryHash,
});

The returned token makes its bindings explicit:

FieldWhat it guarantees
sessionBoundValid only in this session
deviceBoundValid only on this device
challengeBoundValid only for this challenge
bindingStrengthThe strength of the binding
expiresAtWhen it expires
⚠️

The token is single use. The consume result carries alreadyConsumed — if the same token is presented twice, that is where you see it. This is the field that catches a replay.

Threat families

Collected signals are grouped into 17 families:

jailbreak · emulator · frida · hook · clone · reset · mitm · repackaged · attestation_missing · attestation_stale · overlay · remote_control · social_engineering · beneficiary_abuse · integrity · network · policy

The presence of overlay, remote_control and social_engineering is worth noting: these target not a compromised device but a user being directed right now — the classic shape of fraud run through a remote-access app.

Classification

The families reduce to a single surface class:

trusted_surface · suspicious_surface · integrity_elevated · compromised_surface

Freshness

Telemetry can age; its state is returned separately:

fresh · aging · stale · degraded
⚠️

Stale telemetry does not mean clean. When you see stale or degraded, do not treat it as allow — how current a measurement is matters as much as the measurement.

Other capabilities

MethodWhat it does
collectLocalSignals()Reads local signals without going to the server
enableSecureJourneyMode(secureScreen)Turns on screenshot and recording protection on sensitive screens
emitTimelineEvent(...)Adds your own event to the timeline
collectPosTelemetry(...) · evaluatePosThreat(...)A separate surface for POS devices
simulateMobileThreat(...)Scenario simulation for testing your integration
fetchReplayDecision(...) · fetchTraceDecisions(...)Reading past decisions back
getPlatformDiagnostics()The state of the bridge and the native module

The server side

The SDK talks to the gateway's /api/v1/identity/mobile-threat/* endpoints. For the server contract, decision records and the panel side: Mobile Threat

Things to know

🚫

The decision is not made on the client. The SDK produces evidence and carries a typed verdict; the final decision is server-side. Even a fully compromised device cannot fake a clean result, because it is not the thing producing the result.

⚠️

Without the native collectors the bridge package alone does not measure anything meaningful. Make sure the Android and iOS modules are installed; getPlatformDiagnostics() is there to confirm it.

Related

  • SDK Overview — the model shared by the web and mobile families
  • Mobile Threat — the server contract and decision records