freerasp-react-native 4.4.0 → 4.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/android/build.gradle +1 -1
  3. package/android/src/main/java/com/freeraspreactnative/FreeraspReactNativeModule.kt +41 -33
  4. package/android/src/main/java/com/freeraspreactnative/PluginThreatHandler.kt +28 -26
  5. package/android/src/main/java/com/freeraspreactnative/dispatchers/ExecutionStateDispatcher.kt +31 -14
  6. package/android/src/main/java/com/freeraspreactnative/dispatchers/ThreatDispatcher.kt +37 -21
  7. package/example/src/App.tsx +1 -1
  8. package/example/src/checks.ts +1 -1
  9. package/ios/TalsecRuntime.xcframework/_CodeSignature/CodeDirectory +0 -0
  10. package/ios/TalsecRuntime.xcframework/_CodeSignature/CodeResources +82 -288
  11. package/ios/TalsecRuntime.xcframework/_CodeSignature/CodeSignature +0 -0
  12. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/CurlWrapper.h +1 -1
  13. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/TalsecRuntime-Swift.h +7 -2
  14. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/curl.h +7 -7
  15. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/multi.h +4 -4
  16. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/options.h +1 -1
  17. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/urlapi.h +1 -1
  18. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Info.plist +0 -0
  19. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios.abi.json +474 -547
  20. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios.private.swiftinterface +6 -3
  21. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  22. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios.swiftinterface +6 -3
  23. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/PrivacyInfo.xcprivacy +8 -0
  24. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/TalsecRuntime +0 -0
  25. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/CurlWrapper.h +1 -1
  26. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/TalsecRuntime-Swift.h +14 -4
  27. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/curl.h +7 -7
  28. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/multi.h +4 -4
  29. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/options.h +1 -1
  30. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/urlapi.h +1 -1
  31. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Info.plist +0 -0
  32. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios-simulator.abi.json +475 -548
  33. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +6 -3
  34. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  35. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios-simulator.swiftinterface +6 -3
  36. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/x86_64-apple-ios-simulator.abi.json +475 -548
  37. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +6 -3
  38. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  39. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +6 -3
  40. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/PrivacyInfo.xcprivacy +8 -0
  41. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/TalsecRuntime +0 -0
  42. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/_CodeSignature/CodeResources +46 -35
  43. package/ios/models/SecurityThreat.swift +2 -0
  44. package/ios/utils/EventIdentifiers.swift +2 -2
  45. package/lib/commonjs/models/threat.js +1 -1
  46. package/lib/commonjs/models/threat.js.map +1 -1
  47. package/lib/module/models/threat.js +1 -1
  48. package/lib/module/models/threat.js.map +1 -1
  49. package/lib/typescript/src/models/threat.d.ts.map +1 -1
  50. package/package.json +1 -1
  51. package/src/models/threat.ts +1 -0
  52. package/ios/TalsecRuntime.xcframework/_CodeSignature/CodeRequirements-1 +0 -0
package/CHANGELOG.md CHANGED
@@ -5,6 +5,66 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [4.5.1] - 2026-03-16
9
+
10
+ - Android SDK version: 18.0.4
11
+ - iOS SDK version: 6.14.1
12
+
13
+ ### React Native
14
+
15
+ #### Fixed
16
+
17
+ - Fixed case where event dispatchers on Android were not initialized before calling onResume at the app launch
18
+
19
+ ## [4.5.0] - 2026-03-03
20
+
21
+ - Android SDK version: 18.0.4
22
+ - iOS SDK version: 6.14.1
23
+
24
+ ### React Native
25
+
26
+ #### Changed
27
+
28
+ - Updated the internal handling of ExternalIdResult on Android (for `storeExternalId()` method)
29
+
30
+ ### Android
31
+
32
+ #### Added
33
+
34
+ - Added support for `KernelSU` to the existing root detection capabilities
35
+ - Added support for `HMA` to the existing root detection capabilities
36
+ - Added new malware detection capabilities
37
+ - Added `onAutomationDetected()` callback to `ThreatDetected` interface
38
+ - We are introducing a new capability, detecting whether the device is being automated using tools like Appium
39
+ - Added value restrictions to `externalId`
40
+ - Method `storeExternalId()` now returns `ExternalIdResult`, which indicates `Success` or `Error` when `externalId` violates restrictions
41
+
42
+ #### Fixed
43
+
44
+ - Fixed exception handling for the KeyStore `getEntry` operation
45
+ - Fixed issue in `ScreenProtector` concerning the `onScreenRecordingDetected` invocations
46
+ - Merged internal shared libraries into a single one, reducing the final APK size
47
+ - Fixed bug related to key storing in keystore type detection (hw-backed keystore check)
48
+ - Fixed manifest queries merge
49
+
50
+ #### Changed
51
+
52
+ - Removed unused library `tmlib`
53
+ - Refactoring of signature verification code
54
+ - Updated compile and target API to 36
55
+ - Improved root detection capabilities
56
+ - Detection of wireless ADB added to ADB detections
57
+
58
+ ### iOS
59
+
60
+ #### Added
61
+
62
+ - Added time spoofing detection, detecting an inaccurate device clock. It is a new threat `timeSpoofing`.
63
+
64
+ #### Changed
65
+
66
+ - Improved jailbreak detection methods.
67
+
8
68
  ## [4.4.0] - 2026-02-06
9
69
 
10
70
  - Android SDK version: 18.0.1
@@ -105,7 +105,7 @@ dependencies {
105
105
  implementation "com.facebook.react:react-native:$react_native_version"
106
106
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
107
107
  implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1"
108
- implementation "com.aheaditec.talsec.security:TalsecSecurity-Community-ReactNative:18.0.2"
108
+ implementation "com.aheaditec.talsec.security:TalsecSecurity-Community-ReactNative:18.0.4"
109
109
  }
110
110
 
111
111
  if (isNewArchitectureEnabled()) {
@@ -9,7 +9,6 @@ import com.aheaditec.talsec_security.security.api.SuspiciousAppInfo
9
9
  import com.aheaditec.talsec_security.security.api.Talsec
10
10
  import com.aheaditec.talsec_security.security.api.TalsecConfig
11
11
  import com.aheaditec.talsec_security.security.api.TalsecMode
12
- import com.aheaditec.talsec_security.security.api.ThreatListener
13
12
  import com.facebook.react.bridge.Arguments
14
13
  import com.facebook.react.bridge.LifecycleEventListener
15
14
  import com.facebook.react.bridge.Promise
@@ -19,8 +18,10 @@ import com.facebook.react.bridge.ReactMethod
19
18
  import com.facebook.react.bridge.ReadableMap
20
19
  import com.facebook.react.bridge.UiThreadUtil.runOnUiThread
21
20
  import com.facebook.react.bridge.WritableArray
21
+ import com.facebook.react.bridge.WritableMap
22
22
  import com.facebook.react.modules.core.DeviceEventManagerModule
23
- import com.freeraspreactnative.events.BaseRaspEvent
23
+ import com.freeraspreactnative.dispatchers.ExecutionStateDispatcher
24
+ import com.freeraspreactnative.dispatchers.ThreatDispatcher
24
25
  import com.freeraspreactnative.events.RaspExecutionStateEvent
25
26
  import com.freeraspreactnative.events.ThreatEvent
26
27
  import com.freeraspreactnative.interfaces.PluginExecutionStateListener
@@ -38,15 +39,24 @@ class FreeraspReactNativeModule(private val reactContext: ReactApplicationContex
38
39
 
39
40
  private val lifecycleListener = object : LifecycleEventListener {
40
41
  override fun onHostResume() {
42
+ ThreatDispatcher.onResume()
43
+ ExecutionStateDispatcher.onResume()
41
44
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
42
45
  reactContext.currentActivity?.let { ScreenProtector.register(it) }
43
46
  }
44
47
  }
45
48
 
46
49
  override fun onHostPause() {
50
+ ThreatDispatcher.onPause()
51
+ ExecutionStateDispatcher.onPause()
47
52
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
48
53
  reactContext.currentActivity?.let { ScreenProtector.unregister(it) }
49
54
  }
55
+ if (reactContext.currentActivity?.isFinishing == true) {
56
+ ThreatDispatcher.unregisterListener()
57
+ ExecutionStateDispatcher.unregisterListener()
58
+ PluginThreatHandler.unregisterSDKListener(reactContext)
59
+ }
50
60
  }
51
61
 
52
62
  override fun onHostDestroy() {
@@ -58,19 +68,25 @@ class FreeraspReactNativeModule(private val reactContext: ReactApplicationContex
58
68
  return NAME
59
69
  }
60
70
 
61
- init {
71
+ override fun initialize() {
62
72
  reactContext.addLifecycleEventListener(lifecycleListener)
63
73
  initializeEventKeys()
74
+ PluginThreatHandler.initializePluginListener(PluginListener(reactContext))
75
+ super.initialize()
64
76
  }
65
77
 
66
78
  @ReactMethod
67
79
  fun talsecStart(
68
80
  options: ReadableMap, promise: Promise
69
81
  ) {
82
+ if (talsecStarted) {
83
+ promise.resolve("freeRASP started")
84
+ return
85
+ }
70
86
 
71
87
  try {
72
88
  val config = buildTalsecConfig(options)
73
- PluginThreatHandler.registerListener(reactContext)
89
+ PluginThreatHandler.registerSDKListener(reactContext)
74
90
  runOnUiThread {
75
91
  Talsec.start(reactContext, config, TalsecMode.BACKGROUND)
76
92
  mainHandler.post {
@@ -149,10 +165,10 @@ class FreeraspReactNativeModule(private val reactContext: ReactApplicationContex
149
165
  @ReactMethod
150
166
  fun addListener(eventName: String) {
151
167
  if (eventName == ThreatEvent.CHANNEL_NAME) {
152
- PluginThreatHandler.threatDispatcher.listener = PluginListener(reactContext)
168
+ ThreatDispatcher.registerListener(PluginListener(reactContext))
153
169
  }
154
170
  if (eventName == RaspExecutionStateEvent.CHANNEL_NAME) {
155
- PluginThreatHandler.executionStateDispatcher.listener = PluginListener(reactContext)
171
+ ExecutionStateDispatcher.registerListener(PluginListener(reactContext))
156
172
  }
157
173
  }
158
174
 
@@ -165,10 +181,10 @@ class FreeraspReactNativeModule(private val reactContext: ReactApplicationContex
165
181
  @ReactMethod
166
182
  fun removeListenerForEvent(eventName: String, promise: Promise) {
167
183
  if (eventName == ThreatEvent.CHANNEL_NAME) {
168
- PluginThreatHandler.threatDispatcher.listener = null
184
+ ThreatDispatcher.unregisterListener()
169
185
  }
170
186
  if (eventName == RaspExecutionStateEvent.CHANNEL_NAME) {
171
- PluginThreatHandler.executionStateDispatcher.listener = null
187
+ ExecutionStateDispatcher.unregisterListener()
172
188
  }
173
189
  promise.resolve("Listener unregistered")
174
190
  }
@@ -302,48 +318,40 @@ class FreeraspReactNativeModule(private val reactContext: ReactApplicationContex
302
318
  private val mainHandler = Handler(Looper.getMainLooper())
303
319
 
304
320
  internal var talsecStarted = false
321
+ }
322
+
323
+ internal class PluginListener(private val reactContext: ReactApplicationContext) :
324
+ PluginThreatListener, PluginExecutionStateListener {
305
325
 
306
- private fun notifyEvent(event: BaseRaspEvent, appReactContext: ReactApplicationContext) {
326
+ override fun threatDetected(threatEventType: ThreatEvent) {
307
327
  val params = Arguments.createMap()
308
- params.putInt(event.channelKey, event.value)
309
- appReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
310
- .emit(event.channelName, params)
328
+ params.putInt(threatEventType.channelKey, threatEventType.value)
329
+ notifyEvent(ThreatEvent.CHANNEL_NAME, params)
311
330
  }
312
331
 
313
- /**
314
- * Sends malware detected event to React Native
315
- */
316
- private fun notifyMalware(suspiciousApps: MutableList<SuspiciousAppInfo>, appReactContext: ReactApplicationContext) {
317
- // Perform the malware encoding on a background thread
332
+ override fun malwareDetected(suspiciousApps: MutableList<SuspiciousAppInfo>) {
318
333
  backgroundHandler.post {
319
-
320
- val encodedSuspiciousApps = suspiciousApps.toEncodedWritableArray(appReactContext)
321
-
334
+ val encodedSuspiciousApps = suspiciousApps.toEncodedWritableArray(reactContext)
322
335
  mainHandler.post {
323
336
  val params = Arguments.createMap()
324
337
  params.putInt(ThreatEvent.CHANNEL_KEY, ThreatEvent.Malware.value)
325
338
  params.putArray(
326
339
  ThreatEvent.MALWARE_CHANNEL_KEY, encodedSuspiciousApps
327
340
  )
328
-
329
- appReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
330
- .emit(ThreatEvent.CHANNEL_NAME, params)
341
+ notifyEvent(ThreatEvent.CHANNEL_NAME, params)
331
342
  }
332
343
  }
333
344
  }
334
- }
335
-
336
- internal class PluginListener(private val reactContext: ReactApplicationContext) : PluginThreatListener, PluginExecutionStateListener {
337
- override fun threatDetected(threatEventType: ThreatEvent) {
338
- notifyEvent(threatEventType, reactContext)
339
- }
340
345
 
341
- override fun malwareDetected(suspiciousApps: MutableList<SuspiciousAppInfo>) {
342
- notifyMalware(suspiciousApps, reactContext)
346
+ override fun raspExecutionStateChanged(event: RaspExecutionStateEvent) {
347
+ val params = Arguments.createMap()
348
+ params.putInt(event.channelKey, event.value)
349
+ notifyEvent(event.channelName, params)
343
350
  }
344
351
 
345
- override fun raspExecutionStateChanged(event: RaspExecutionStateEvent) {
346
- notifyEvent(event, reactContext)
352
+ private fun notifyEvent(eventName: String, params: WritableMap) {
353
+ reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
354
+ .emit(eventName, params)
347
355
  }
348
356
  }
349
357
  }
@@ -10,112 +10,114 @@ import com.freeraspreactnative.events.ThreatEvent
10
10
 
11
11
  internal object PluginThreatHandler {
12
12
 
13
- internal val threatDispatcher = ThreatDispatcher()
14
- internal val executionStateDispatcher = ExecutionStateDispatcher()
13
+ fun initializePluginListener(listener: FreeraspReactNativeModule.PluginListener) {
14
+ ThreatDispatcher.listener = listener
15
+ ExecutionStateDispatcher.listener = listener
16
+ }
15
17
 
16
18
  private val threatDetected = object : ThreatListener.ThreatDetected() {
17
19
 
18
20
  override fun onRootDetected() {
19
- threatDispatcher.dispatchThreat(ThreatEvent.PrivilegedAccess)
21
+ ThreatDispatcher.dispatchThreat(ThreatEvent.PrivilegedAccess)
20
22
  }
21
23
 
22
24
  override fun onDebuggerDetected() {
23
- threatDispatcher.dispatchThreat(ThreatEvent.Debug)
25
+ ThreatDispatcher.dispatchThreat(ThreatEvent.Debug)
24
26
  }
25
27
 
26
28
  override fun onEmulatorDetected() {
27
- threatDispatcher.dispatchThreat(ThreatEvent.Simulator)
29
+ ThreatDispatcher.dispatchThreat(ThreatEvent.Simulator)
28
30
  }
29
31
 
30
32
  override fun onTamperDetected() {
31
- threatDispatcher.dispatchThreat(ThreatEvent.AppIntegrity)
33
+ ThreatDispatcher.dispatchThreat(ThreatEvent.AppIntegrity)
32
34
  }
33
35
 
34
36
  override fun onUntrustedInstallationSourceDetected() {
35
- threatDispatcher.dispatchThreat(ThreatEvent.UnofficialStore)
37
+ ThreatDispatcher.dispatchThreat(ThreatEvent.UnofficialStore)
36
38
  }
37
39
 
38
40
  override fun onHookDetected() {
39
- threatDispatcher.dispatchThreat(ThreatEvent.Hooks)
41
+ ThreatDispatcher.dispatchThreat(ThreatEvent.Hooks)
40
42
  }
41
43
 
42
44
  override fun onDeviceBindingDetected() {
43
- threatDispatcher.dispatchThreat(ThreatEvent.DeviceBinding)
45
+ ThreatDispatcher.dispatchThreat(ThreatEvent.DeviceBinding)
44
46
  }
45
47
 
46
48
  override fun onObfuscationIssuesDetected() {
47
- threatDispatcher.dispatchThreat(ThreatEvent.ObfuscationIssues)
49
+ ThreatDispatcher.dispatchThreat(ThreatEvent.ObfuscationIssues)
48
50
  }
49
51
 
50
52
  override fun onMalwareDetected(suspiciousAppInfos: MutableList<SuspiciousAppInfo>) {
51
- threatDispatcher.dispatchMalware(suspiciousAppInfos ?: mutableListOf())
53
+ ThreatDispatcher.dispatchMalware(suspiciousAppInfos ?: mutableListOf())
52
54
  }
53
55
 
54
56
  override fun onScreenshotDetected() {
55
- threatDispatcher.dispatchThreat(ThreatEvent.Screenshot)
57
+ ThreatDispatcher.dispatchThreat(ThreatEvent.Screenshot)
56
58
  }
57
59
 
58
60
  override fun onScreenRecordingDetected() {
59
- threatDispatcher.dispatchThreat(ThreatEvent.ScreenRecording)
61
+ ThreatDispatcher.dispatchThreat(ThreatEvent.ScreenRecording)
60
62
  }
61
63
 
62
64
  override fun onMultiInstanceDetected() {
63
- threatDispatcher.dispatchThreat(ThreatEvent.MultiInstance)
65
+ ThreatDispatcher.dispatchThreat(ThreatEvent.MultiInstance)
64
66
  }
65
67
 
66
68
  override fun onUnsecureWifiDetected() {
67
- threatDispatcher.dispatchThreat(ThreatEvent.UnsecureWifi)
69
+ ThreatDispatcher.dispatchThreat(ThreatEvent.UnsecureWifi)
68
70
  }
69
71
 
70
72
  override fun onTimeSpoofingDetected() {
71
- threatDispatcher.dispatchThreat(ThreatEvent.TimeSpoofing)
73
+ ThreatDispatcher.dispatchThreat(ThreatEvent.TimeSpoofing)
72
74
  }
73
75
 
74
76
  override fun onLocationSpoofingDetected() {
75
- threatDispatcher.dispatchThreat(ThreatEvent.LocationSpoofing)
77
+ ThreatDispatcher.dispatchThreat(ThreatEvent.LocationSpoofing)
76
78
  }
77
79
 
78
80
  override fun onAutomationDetected() {
79
- threatDispatcher.dispatchThreat(ThreatEvent.Automation)
81
+ ThreatDispatcher.dispatchThreat(ThreatEvent.Automation)
80
82
  }
81
83
  }
82
84
 
83
85
  private val deviceState = object : ThreatListener.DeviceState() {
84
86
 
85
87
  override fun onUnlockedDeviceDetected() {
86
- threatDispatcher.dispatchThreat(ThreatEvent.Passcode)
88
+ ThreatDispatcher.dispatchThreat(ThreatEvent.Passcode)
87
89
  }
88
90
 
89
91
  override fun onHardwareBackedKeystoreNotAvailableDetected() {
90
- threatDispatcher.dispatchThreat(ThreatEvent.SecureHardwareNotAvailable)
92
+ ThreatDispatcher.dispatchThreat(ThreatEvent.SecureHardwareNotAvailable)
91
93
  }
92
94
 
93
95
  override fun onDeveloperModeDetected() {
94
- threatDispatcher.dispatchThreat(ThreatEvent.DevMode)
96
+ ThreatDispatcher.dispatchThreat(ThreatEvent.DevMode)
95
97
  }
96
98
 
97
99
  override fun onADBEnabledDetected() {
98
- threatDispatcher.dispatchThreat(ThreatEvent.ADBEnabled)
100
+ ThreatDispatcher.dispatchThreat(ThreatEvent.ADBEnabled)
99
101
  }
100
102
 
101
103
  override fun onSystemVPNDetected() {
102
- threatDispatcher.dispatchThreat(ThreatEvent.SystemVPN)
104
+ ThreatDispatcher.dispatchThreat(ThreatEvent.SystemVPN)
103
105
  }
104
106
  }
105
107
 
106
108
  private val raspExecutionState = object : ThreatListener.RaspExecutionState() {
107
109
  override fun onAllChecksFinished() {
108
- executionStateDispatcher.dispatch(RaspExecutionStateEvent.AllChecksFinished)
110
+ ExecutionStateDispatcher.dispatch(RaspExecutionStateEvent.AllChecksFinished)
109
111
  }
110
112
  }
111
113
 
112
114
  private val internalListener = ThreatListener(threatDetected, deviceState, raspExecutionState)
113
115
 
114
- internal fun registerListener(context: Context) {
116
+ internal fun registerSDKListener(context: Context) {
115
117
  internalListener.registerListener(context)
116
118
  }
117
119
 
118
- internal fun unregisterListener(context: Context) {
120
+ internal fun unregisterSDKListener(context: Context) {
119
121
  internalListener.unregisterListener(context)
120
122
  }
121
123
  }
@@ -3,36 +3,53 @@ package com.freeraspreactnative.dispatchers
3
3
  import com.freeraspreactnative.events.RaspExecutionStateEvent
4
4
  import com.freeraspreactnative.interfaces.PluginExecutionStateListener
5
5
 
6
- internal class ExecutionStateDispatcher {
6
+ internal object ExecutionStateDispatcher {
7
+ lateinit var listener: PluginExecutionStateListener
7
8
  private val cache = mutableSetOf<RaspExecutionStateEvent>()
8
9
 
9
- var listener: PluginExecutionStateListener? = null
10
- set(value) {
11
- field = value
12
- if (value != null) {
13
- flushCache(value)
14
- }
10
+ private var isAppInForeground = false
11
+ private var isListenerRegistered = false
12
+
13
+ fun registerListener(newListener: PluginExecutionStateListener) {
14
+ listener = newListener
15
+ isListenerRegistered = true
16
+ isAppInForeground = true
17
+ flushCache()
18
+ }
19
+
20
+ fun unregisterListener() {
21
+ isListenerRegistered = false
22
+ isAppInForeground = false
23
+ }
24
+
25
+ fun onResume() {
26
+ isAppInForeground = true
27
+ if (isListenerRegistered) {
28
+ flushCache()
15
29
  }
30
+ }
31
+
32
+ fun onPause() {
33
+ isAppInForeground = false
34
+ }
16
35
 
17
36
  fun dispatch(event: RaspExecutionStateEvent) {
18
- val currentListener = listener
19
- if (currentListener != null) {
20
- currentListener.raspExecutionStateChanged(event)
37
+ if (isAppInForeground && isListenerRegistered) {
38
+ listener.raspExecutionStateChanged(event)
21
39
  } else {
22
40
  synchronized(cache) {
23
- val checkedListener = listener
24
- checkedListener?.raspExecutionStateChanged(event) ?: cache.add(event)
41
+ cache.add(event)
25
42
  }
26
43
  }
27
44
  }
28
45
 
29
- private fun flushCache(registeredListener: PluginExecutionStateListener) {
46
+ private fun flushCache() {
30
47
  val events = synchronized(cache) {
31
48
  val snapshot = cache.toSet()
32
49
  cache.clear()
33
50
  snapshot
34
51
  }
35
- events.forEach { registeredListener.raspExecutionStateChanged(it) }
52
+ events.forEach { listener.raspExecutionStateChanged(it) }
36
53
  }
37
54
  }
38
55
 
@@ -4,49 +4,65 @@ import com.aheaditec.talsec_security.security.api.SuspiciousAppInfo
4
4
  import com.freeraspreactnative.events.ThreatEvent
5
5
  import com.freeraspreactnative.interfaces.PluginThreatListener
6
6
 
7
- internal class ThreatDispatcher {
7
+ internal object ThreatDispatcher {
8
+ lateinit var listener: PluginThreatListener
8
9
  private val threatCache = mutableSetOf<ThreatEvent>()
9
10
  private val malwareCache = mutableSetOf<SuspiciousAppInfo>()
10
11
 
11
- var listener: PluginThreatListener? = null
12
- set(value) {
13
- field = value
14
- if (value != null) {
15
- flushCache(value)
16
- }
12
+ private var isAppInForeground = false
13
+ private var isListenerRegistered = false
14
+
15
+ fun registerListener(newListener: PluginThreatListener) {
16
+ listener = newListener
17
+ isListenerRegistered = true
18
+ isAppInForeground = true
19
+ flushCache()
20
+ }
21
+
22
+ fun unregisterListener() {
23
+ isListenerRegistered = false
24
+ isAppInForeground = false
25
+ }
26
+
27
+ fun onResume() {
28
+ isAppInForeground = true
29
+ if (isListenerRegistered) {
30
+ flushCache()
17
31
  }
32
+ }
33
+
34
+ fun onPause() {
35
+ isAppInForeground = false
36
+ }
18
37
 
19
38
  fun dispatchThreat(event: ThreatEvent) {
20
- val currentListener = listener
21
- if (currentListener != null) {
22
- currentListener.threatDetected(event)
39
+ if (isAppInForeground && isListenerRegistered) {
40
+ listener.threatDetected(event)
23
41
  } else {
24
42
  synchronized(threatCache) {
25
- val checkedListener = listener
26
- checkedListener?.threatDetected(event) ?: threatCache.add(event)
43
+ threatCache.add(event)
27
44
  }
28
45
  }
29
46
  }
30
47
 
31
48
  fun dispatchMalware(apps: MutableList<SuspiciousAppInfo>) {
32
- val currentListener = listener
33
- if (currentListener != null) {
34
- currentListener.malwareDetected(apps)
35
- } else {
49
+ if (isAppInForeground && isListenerRegistered) {
50
+ listener.malwareDetected(apps)
51
+ }
52
+ else {
36
53
  synchronized(malwareCache) {
37
- val checkedListener = listener
38
- checkedListener?.malwareDetected(apps) ?: malwareCache.addAll(apps)
54
+ malwareCache.addAll(apps)
39
55
  }
40
56
  }
41
57
  }
42
58
 
43
- private fun flushCache(registeredListener: PluginThreatListener) {
59
+ private fun flushCache() {
44
60
  val threats = synchronized(threatCache) {
45
61
  val snapshot = threatCache.toSet()
46
62
  threatCache.clear()
47
63
  snapshot
48
64
  }
49
- threats.forEach { registeredListener.threatDetected(it) }
65
+ threats.forEach { listener.threatDetected(it) }
50
66
 
51
67
  val malware = synchronized(malwareCache) {
52
68
  val snapshot = malwareCache.toMutableList()
@@ -54,7 +70,7 @@ internal class ThreatDispatcher {
54
70
  snapshot
55
71
  }
56
72
  if (malware.isNotEmpty()) {
57
- registeredListener.malwareDetected(malware)
73
+ listener.malwareDetected(malware)
58
74
  }
59
75
  }
60
76
  }
@@ -221,7 +221,7 @@ const App = () => {
221
221
  )
222
222
  );
223
223
  },
224
- // Android only
224
+ // Android & iOS
225
225
  timeSpoofing: () => {
226
226
  setAppChecks((currentState) =>
227
227
  currentState.map((threat) =>
@@ -11,6 +11,7 @@ export const commonChecks = [
11
11
  { name: 'Unofficial Store', status: 'ok' },
12
12
  { name: 'Screenshot', status: 'ok' },
13
13
  { name: 'Screen Recording', status: 'ok' },
14
+ { name: 'Time Spoofing', status: 'ok' },
14
15
  ];
15
16
 
16
17
  export const iosChecks = [{ name: 'Device ID', status: 'ok' }];
@@ -21,7 +22,6 @@ export const androidChecks = [
21
22
  { name: 'Malware', status: 'ok' },
22
23
  { name: 'ADB Enabled', status: 'ok' },
23
24
  { name: 'Multi Instance', status: 'ok' },
24
- { name: 'Time Spoofing', status: 'ok' },
25
25
  { name: 'Location Spoofing', status: 'ok' },
26
26
  { name: 'Unsecure Wifi', status: 'ok' },
27
27
  { name: 'Automation', status: 'ok' },