freerasp-react-native 4.4.0 → 4.5.0

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 +49 -0
  2. package/android/build.gradle +1 -1
  3. package/android/src/main/java/com/freeraspreactnative/FreeraspReactNativeModule.kt +37 -32
  4. package/android/src/main/java/com/freeraspreactnative/PluginThreatHandler.kt +9 -4
  5. package/android/src/main/java/com/freeraspreactnative/dispatchers/ExecutionStateDispatcher.kt +29 -14
  6. package/android/src/main/java/com/freeraspreactnative/dispatchers/ThreatDispatcher.kt +35 -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,55 @@ 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.0] - 2026-03-03
9
+
10
+ - Android SDK version: 18.0.4
11
+ - iOS SDK version: 6.14.1
12
+
13
+ ### React Native
14
+
15
+ #### Changed
16
+
17
+ - Updated the internal handling of ExternalIdResult on Android (for `storeExternalId()` method)
18
+
19
+ ### Android
20
+
21
+ #### Added
22
+
23
+ - Added support for `KernelSU` to the existing root detection capabilities
24
+ - Added support for `HMA` to the existing root detection capabilities
25
+ - Added new malware detection capabilities
26
+ - Added `onAutomationDetected()` callback to `ThreatDetected` interface
27
+ - We are introducing a new capability, detecting whether the device is being automated using tools like Appium
28
+ - Added value restrictions to `externalId`
29
+ - Method `storeExternalId()` now returns `ExternalIdResult`, which indicates `Success` or `Error` when `externalId` violates restrictions
30
+
31
+ #### Fixed
32
+
33
+ - Fixed exception handling for the KeyStore `getEntry` operation
34
+ - Fixed issue in `ScreenProtector` concerning the `onScreenRecordingDetected` invocations
35
+ - Merged internal shared libraries into a single one, reducing the final APK size
36
+ - Fixed bug related to key storing in keystore type detection (hw-backed keystore check)
37
+ - Fixed manifest queries merge
38
+
39
+ #### Changed
40
+
41
+ - Removed unused library `tmlib`
42
+ - Refactoring of signature verification code
43
+ - Updated compile and target API to 36
44
+ - Improved root detection capabilities
45
+ - Detection of wireless ADB added to ADB detections
46
+
47
+ ### iOS
48
+
49
+ #### Added
50
+
51
+ - Added time spoofing detection, detecting an inaccurate device clock. It is a new threat `timeSpoofing`.
52
+
53
+ #### Changed
54
+
55
+ - Improved jailbreak detection methods.
56
+
8
57
  ## [4.4.0] - 2026-02-06
9
58
 
10
59
  - 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,8 @@ 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
24
23
  import com.freeraspreactnative.events.RaspExecutionStateEvent
25
24
  import com.freeraspreactnative.events.ThreatEvent
26
25
  import com.freeraspreactnative.interfaces.PluginExecutionStateListener
@@ -38,15 +37,24 @@ class FreeraspReactNativeModule(private val reactContext: ReactApplicationContex
38
37
 
39
38
  private val lifecycleListener = object : LifecycleEventListener {
40
39
  override fun onHostResume() {
40
+ PluginThreatHandler.threatDispatcher.onResume()
41
+ PluginThreatHandler.executionStateDispatcher.onResume()
41
42
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
42
43
  reactContext.currentActivity?.let { ScreenProtector.register(it) }
43
44
  }
44
45
  }
45
46
 
46
47
  override fun onHostPause() {
48
+ PluginThreatHandler.threatDispatcher.onPause()
49
+ PluginThreatHandler.executionStateDispatcher.onPause()
47
50
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
48
51
  reactContext.currentActivity?.let { ScreenProtector.unregister(it) }
49
52
  }
53
+ if (reactContext.currentActivity?.isFinishing == true) {
54
+ PluginThreatHandler.threatDispatcher.unregisterListener()
55
+ PluginThreatHandler.executionStateDispatcher.unregisterListener()
56
+ PluginThreatHandler.unregisterSDKListener(reactContext)
57
+ }
50
58
  }
51
59
 
52
60
  override fun onHostDestroy() {
@@ -61,16 +69,21 @@ class FreeraspReactNativeModule(private val reactContext: ReactApplicationContex
61
69
  init {
62
70
  reactContext.addLifecycleEventListener(lifecycleListener)
63
71
  initializeEventKeys()
72
+ PluginThreatHandler.initializeDispatchers(PluginListener(reactContext))
64
73
  }
65
74
 
66
75
  @ReactMethod
67
76
  fun talsecStart(
68
77
  options: ReadableMap, promise: Promise
69
78
  ) {
79
+ if (talsecStarted) {
80
+ promise.resolve("freeRASP started")
81
+ return
82
+ }
70
83
 
71
84
  try {
72
85
  val config = buildTalsecConfig(options)
73
- PluginThreatHandler.registerListener(reactContext)
86
+ PluginThreatHandler.registerSDKListener(reactContext)
74
87
  runOnUiThread {
75
88
  Talsec.start(reactContext, config, TalsecMode.BACKGROUND)
76
89
  mainHandler.post {
@@ -149,10 +162,10 @@ class FreeraspReactNativeModule(private val reactContext: ReactApplicationContex
149
162
  @ReactMethod
150
163
  fun addListener(eventName: String) {
151
164
  if (eventName == ThreatEvent.CHANNEL_NAME) {
152
- PluginThreatHandler.threatDispatcher.listener = PluginListener(reactContext)
165
+ PluginThreatHandler.threatDispatcher.registerListener()
153
166
  }
154
167
  if (eventName == RaspExecutionStateEvent.CHANNEL_NAME) {
155
- PluginThreatHandler.executionStateDispatcher.listener = PluginListener(reactContext)
168
+ PluginThreatHandler.executionStateDispatcher.registerListener()
156
169
  }
157
170
  }
158
171
 
@@ -165,10 +178,10 @@ class FreeraspReactNativeModule(private val reactContext: ReactApplicationContex
165
178
  @ReactMethod
166
179
  fun removeListenerForEvent(eventName: String, promise: Promise) {
167
180
  if (eventName == ThreatEvent.CHANNEL_NAME) {
168
- PluginThreatHandler.threatDispatcher.listener = null
181
+ PluginThreatHandler.threatDispatcher.unregisterListener()
169
182
  }
170
183
  if (eventName == RaspExecutionStateEvent.CHANNEL_NAME) {
171
- PluginThreatHandler.executionStateDispatcher.listener = null
184
+ PluginThreatHandler.executionStateDispatcher.unregisterListener()
172
185
  }
173
186
  promise.resolve("Listener unregistered")
174
187
  }
@@ -302,48 +315,40 @@ class FreeraspReactNativeModule(private val reactContext: ReactApplicationContex
302
315
  private val mainHandler = Handler(Looper.getMainLooper())
303
316
 
304
317
  internal var talsecStarted = false
318
+ }
319
+
320
+ internal class PluginListener(private val reactContext: ReactApplicationContext) :
321
+ PluginThreatListener, PluginExecutionStateListener {
305
322
 
306
- private fun notifyEvent(event: BaseRaspEvent, appReactContext: ReactApplicationContext) {
323
+ override fun threatDetected(threatEventType: ThreatEvent) {
307
324
  val params = Arguments.createMap()
308
- params.putInt(event.channelKey, event.value)
309
- appReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
310
- .emit(event.channelName, params)
325
+ params.putInt(threatEventType.channelKey, threatEventType.value)
326
+ notifyEvent(ThreatEvent.CHANNEL_NAME, params)
311
327
  }
312
328
 
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
329
+ override fun malwareDetected(suspiciousApps: MutableList<SuspiciousAppInfo>) {
318
330
  backgroundHandler.post {
319
-
320
- val encodedSuspiciousApps = suspiciousApps.toEncodedWritableArray(appReactContext)
321
-
331
+ val encodedSuspiciousApps = suspiciousApps.toEncodedWritableArray(reactContext)
322
332
  mainHandler.post {
323
333
  val params = Arguments.createMap()
324
334
  params.putInt(ThreatEvent.CHANNEL_KEY, ThreatEvent.Malware.value)
325
335
  params.putArray(
326
336
  ThreatEvent.MALWARE_CHANNEL_KEY, encodedSuspiciousApps
327
337
  )
328
-
329
- appReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
330
- .emit(ThreatEvent.CHANNEL_NAME, params)
338
+ notifyEvent(ThreatEvent.CHANNEL_NAME, params)
331
339
  }
332
340
  }
333
341
  }
334
- }
335
-
336
- internal class PluginListener(private val reactContext: ReactApplicationContext) : PluginThreatListener, PluginExecutionStateListener {
337
- override fun threatDetected(threatEventType: ThreatEvent) {
338
- notifyEvent(threatEventType, reactContext)
339
- }
340
342
 
341
- override fun malwareDetected(suspiciousApps: MutableList<SuspiciousAppInfo>) {
342
- notifyMalware(suspiciousApps, reactContext)
343
+ override fun raspExecutionStateChanged(event: RaspExecutionStateEvent) {
344
+ val params = Arguments.createMap()
345
+ params.putInt(event.channelKey, event.value)
346
+ notifyEvent(event.channelName, params)
343
347
  }
344
348
 
345
- override fun raspExecutionStateChanged(event: RaspExecutionStateEvent) {
346
- notifyEvent(event, reactContext)
349
+ private fun notifyEvent(eventName: String, params: WritableMap) {
350
+ reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
351
+ .emit(eventName, params)
347
352
  }
348
353
  }
349
354
  }
@@ -10,8 +10,13 @@ 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
+ internal lateinit var threatDispatcher: ThreatDispatcher
14
+ internal lateinit var executionStateDispatcher: ExecutionStateDispatcher
15
+
16
+ fun initializeDispatchers(listener: FreeraspReactNativeModule.PluginListener) {
17
+ threatDispatcher = ThreatDispatcher(listener)
18
+ executionStateDispatcher = ExecutionStateDispatcher(listener)
19
+ }
15
20
 
16
21
  private val threatDetected = object : ThreatListener.ThreatDetected() {
17
22
 
@@ -111,11 +116,11 @@ internal object PluginThreatHandler {
111
116
 
112
117
  private val internalListener = ThreatListener(threatDetected, deviceState, raspExecutionState)
113
118
 
114
- internal fun registerListener(context: Context) {
119
+ internal fun registerSDKListener(context: Context) {
115
120
  internalListener.registerListener(context)
116
121
  }
117
122
 
118
- internal fun unregisterListener(context: Context) {
123
+ internal fun unregisterSDKListener(context: Context) {
119
124
  internalListener.unregisterListener(context)
120
125
  }
121
126
  }
@@ -3,36 +3,51 @@ 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 class ExecutionStateDispatcher(private val listener: PluginExecutionStateListener) {
7
7
  private val cache = mutableSetOf<RaspExecutionStateEvent>()
8
8
 
9
- var listener: PluginExecutionStateListener? = null
10
- set(value) {
11
- field = value
12
- if (value != null) {
13
- flushCache(value)
14
- }
9
+ private var isAppInForeground = false
10
+ private var isListenerRegistered = false
11
+
12
+ fun registerListener() {
13
+ isListenerRegistered = true
14
+ isAppInForeground = true
15
+ flushCache()
16
+ }
17
+
18
+ fun unregisterListener() {
19
+ isListenerRegistered = false
20
+ isAppInForeground = false
21
+ }
22
+
23
+ fun onResume() {
24
+ isAppInForeground = true
25
+ if (isListenerRegistered) {
26
+ flushCache()
15
27
  }
28
+ }
29
+
30
+ fun onPause() {
31
+ isAppInForeground = false
32
+ }
16
33
 
17
34
  fun dispatch(event: RaspExecutionStateEvent) {
18
- val currentListener = listener
19
- if (currentListener != null) {
20
- currentListener.raspExecutionStateChanged(event)
35
+ if (isAppInForeground && isListenerRegistered) {
36
+ listener.raspExecutionStateChanged(event)
21
37
  } else {
22
38
  synchronized(cache) {
23
- val checkedListener = listener
24
- checkedListener?.raspExecutionStateChanged(event) ?: cache.add(event)
39
+ cache.add(event)
25
40
  }
26
41
  }
27
42
  }
28
43
 
29
- private fun flushCache(registeredListener: PluginExecutionStateListener) {
44
+ private fun flushCache() {
30
45
  val events = synchronized(cache) {
31
46
  val snapshot = cache.toSet()
32
47
  cache.clear()
33
48
  snapshot
34
49
  }
35
- events.forEach { registeredListener.raspExecutionStateChanged(it) }
50
+ events.forEach { listener.raspExecutionStateChanged(it) }
36
51
  }
37
52
  }
38
53
 
@@ -4,49 +4,63 @@ 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 class ThreatDispatcher(private val listener: PluginThreatListener) {
8
8
  private val threatCache = mutableSetOf<ThreatEvent>()
9
9
  private val malwareCache = mutableSetOf<SuspiciousAppInfo>()
10
10
 
11
- var listener: PluginThreatListener? = null
12
- set(value) {
13
- field = value
14
- if (value != null) {
15
- flushCache(value)
16
- }
11
+ private var isAppInForeground = false
12
+ private var isListenerRegistered = false
13
+
14
+ fun registerListener() {
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()
17
29
  }
30
+ }
31
+
32
+ fun onPause() {
33
+ isAppInForeground = false
34
+ }
18
35
 
19
36
  fun dispatchThreat(event: ThreatEvent) {
20
- val currentListener = listener
21
- if (currentListener != null) {
22
- currentListener.threatDetected(event)
37
+ if (isAppInForeground && isListenerRegistered) {
38
+ listener.threatDetected(event)
23
39
  } else {
24
40
  synchronized(threatCache) {
25
- val checkedListener = listener
26
- checkedListener?.threatDetected(event) ?: threatCache.add(event)
41
+ threatCache.add(event)
27
42
  }
28
43
  }
29
44
  }
30
45
 
31
46
  fun dispatchMalware(apps: MutableList<SuspiciousAppInfo>) {
32
- val currentListener = listener
33
- if (currentListener != null) {
34
- currentListener.malwareDetected(apps)
35
- } else {
47
+ if (isAppInForeground && isListenerRegistered) {
48
+ listener.malwareDetected(apps)
49
+ }
50
+ else {
36
51
  synchronized(malwareCache) {
37
- val checkedListener = listener
38
- checkedListener?.malwareDetected(apps) ?: malwareCache.addAll(apps)
52
+ malwareCache.addAll(apps)
39
53
  }
40
54
  }
41
55
  }
42
56
 
43
- private fun flushCache(registeredListener: PluginThreatListener) {
57
+ private fun flushCache() {
44
58
  val threats = synchronized(threatCache) {
45
59
  val snapshot = threatCache.toSet()
46
60
  threatCache.clear()
47
61
  snapshot
48
62
  }
49
- threats.forEach { registeredListener.threatDetected(it) }
63
+ threats.forEach { listener.threatDetected(it) }
50
64
 
51
65
  val malware = synchronized(malwareCache) {
52
66
  val snapshot = malwareCache.toMutableList()
@@ -54,7 +68,7 @@ internal class ThreatDispatcher {
54
68
  snapshot
55
69
  }
56
70
  if (malware.isNotEmpty()) {
57
- registeredListener.malwareDetected(malware)
71
+ listener.malwareDetected(malware)
58
72
  }
59
73
  }
60
74
  }
@@ -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' },