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.
| Platform | Package | Version |
|---|---|---|
| Flutter | lunixi_mobile_threat_sdk | 0.1.0 |
| React Native | @lunixi/mobile-threat-react-native | 0.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 · denystep_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:
| Field | Required | Meaning |
|---|---|---|
merchantId · sessionId | yes | Tenant and session |
subjectType · subjectId | yes | What you are evaluating (customer, device…) |
sdkVersion | yes | The bridge package's version |
traceId · customerId · paymentId · entryPoint | no | Correlation 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:
| Field | What it guarantees |
|---|---|
sessionBound | Valid only in this session |
deviceBound | Valid only on this device |
challengeBound | Valid only for this challenge |
bindingStrength | The strength of the binding |
expiresAt | When 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_surfaceFreshness
Telemetry can age; its state is returned separately:
fresh · aging · stale · degradedStale 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
| Method | What 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