freerasp-react-native 4.3.2 → 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 (100) hide show
  1. package/CHANGELOG.md +99 -1
  2. package/android/build.gradle +8 -2
  3. package/android/gradle.properties +2 -2
  4. package/android/src/main/java/com/freeraspreactnative/FreeraspReactNativeModule.kt +87 -43
  5. package/android/src/main/java/com/freeraspreactnative/PluginThreatHandler.kt +126 -0
  6. package/android/src/main/java/com/freeraspreactnative/dispatchers/ExecutionStateDispatcher.kt +53 -0
  7. package/android/src/main/java/com/freeraspreactnative/dispatchers/ThreatDispatcher.kt +75 -0
  8. package/android/src/main/java/com/freeraspreactnative/events/ThreatEvent.kt +3 -1
  9. package/android/src/main/java/com/freeraspreactnative/interfaces/PluginExecutionStateListener.kt +7 -0
  10. package/android/src/main/java/com/freeraspreactnative/interfaces/PluginThreatListener.kt +9 -0
  11. package/example/src/App.tsx +11 -1
  12. package/example/src/DemoApp.tsx +32 -0
  13. package/example/src/checks.ts +2 -1
  14. package/freerasp-react-native.podspec +5 -1
  15. package/ios/FreeraspReactNative.m +5 -0
  16. package/ios/FreeraspReactNative.swift +39 -10
  17. package/ios/TalsecRuntime.xcframework/_CodeSignature/CodeDirectory +0 -0
  18. package/ios/TalsecRuntime.xcframework/_CodeSignature/CodeResources +82 -288
  19. package/ios/TalsecRuntime.xcframework/_CodeSignature/CodeSignature +0 -0
  20. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/CurlWrapper.h +1 -1
  21. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/TalsecRuntime-Swift.h +7 -2
  22. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/curl.h +7 -7
  23. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/multi.h +4 -4
  24. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/options.h +1 -1
  25. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/urlapi.h +1 -1
  26. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Info.plist +0 -0
  27. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios.abi.json +474 -547
  28. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios.private.swiftinterface +6 -3
  29. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  30. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios.swiftinterface +6 -3
  31. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/PrivacyInfo.xcprivacy +8 -0
  32. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/TalsecRuntime +0 -0
  33. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/CurlWrapper.h +1 -1
  34. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/TalsecRuntime-Swift.h +14 -4
  35. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/curl.h +7 -7
  36. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/multi.h +4 -4
  37. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/options.h +1 -1
  38. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/urlapi.h +1 -1
  39. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Info.plist +0 -0
  40. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios-simulator.abi.json +475 -548
  41. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +6 -3
  42. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  43. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios-simulator.swiftinterface +6 -3
  44. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/x86_64-apple-ios-simulator.abi.json +475 -548
  45. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +6 -3
  46. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  47. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +6 -3
  48. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/PrivacyInfo.xcprivacy +8 -0
  49. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/TalsecRuntime +0 -0
  50. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/_CodeSignature/CodeResources +46 -35
  51. package/ios/dispatchers/ExecutionStateDispatcher.swift +35 -0
  52. package/ios/dispatchers/ThreatDispatcher.swift +36 -0
  53. package/ios/models/SecurityThreat.swift +2 -0
  54. package/ios/utils/EventIdentifiers.swift +2 -2
  55. package/lib/commonjs/api/listeners/raspExecutionState.js +28 -8
  56. package/lib/commonjs/api/listeners/raspExecutionState.js.map +1 -1
  57. package/lib/commonjs/api/listeners/threat.js +34 -10
  58. package/lib/commonjs/api/listeners/threat.js.map +1 -1
  59. package/lib/commonjs/api/methods/native.js +9 -1
  60. package/lib/commonjs/api/methods/native.js.map +1 -1
  61. package/lib/commonjs/api/methods/reactNative.js +13 -8
  62. package/lib/commonjs/api/methods/reactNative.js.map +1 -1
  63. package/lib/commonjs/channels/threat.js +1 -3
  64. package/lib/commonjs/channels/threat.js.map +1 -1
  65. package/lib/commonjs/models/threat.js +2 -1
  66. package/lib/commonjs/models/threat.js.map +1 -1
  67. package/lib/module/api/listeners/raspExecutionState.js +29 -9
  68. package/lib/module/api/listeners/raspExecutionState.js.map +1 -1
  69. package/lib/module/api/listeners/threat.js +35 -11
  70. package/lib/module/api/listeners/threat.js.map +1 -1
  71. package/lib/module/api/methods/native.js +6 -0
  72. package/lib/module/api/methods/native.js.map +1 -1
  73. package/lib/module/api/methods/reactNative.js +13 -7
  74. package/lib/module/api/methods/reactNative.js.map +1 -1
  75. package/lib/module/channels/threat.js +1 -3
  76. package/lib/module/channels/threat.js.map +1 -1
  77. package/lib/module/models/threat.js +2 -1
  78. package/lib/module/models/threat.js.map +1 -1
  79. package/lib/typescript/src/api/listeners/raspExecutionState.d.ts +1 -1
  80. package/lib/typescript/src/api/listeners/raspExecutionState.d.ts.map +1 -1
  81. package/lib/typescript/src/api/listeners/threat.d.ts +1 -1
  82. package/lib/typescript/src/api/listeners/threat.d.ts.map +1 -1
  83. package/lib/typescript/src/api/methods/native.d.ts +2 -0
  84. package/lib/typescript/src/api/methods/native.d.ts.map +1 -1
  85. package/lib/typescript/src/api/methods/reactNative.d.ts.map +1 -1
  86. package/lib/typescript/src/channels/threat.d.ts.map +1 -1
  87. package/lib/typescript/src/models/threat.d.ts +1 -0
  88. package/lib/typescript/src/models/threat.d.ts.map +1 -1
  89. package/lib/typescript/src/types/types.d.ts +1 -0
  90. package/lib/typescript/src/types/types.d.ts.map +1 -1
  91. package/package.json +1 -1
  92. package/src/api/listeners/raspExecutionState.ts +39 -11
  93. package/src/api/listeners/threat.ts +41 -10
  94. package/src/api/methods/native.ts +8 -0
  95. package/src/api/methods/reactNative.ts +17 -8
  96. package/src/channels/threat.ts +1 -3
  97. package/src/models/threat.ts +3 -0
  98. package/src/types/types.ts +1 -0
  99. package/android/src/main/java/com/freeraspreactnative/FreeraspThreatHandler.kt +0 -103
  100. package/ios/TalsecRuntime.xcframework/_CodeSignature/CodeRequirements-1 +0 -0
package/CHANGELOG.md CHANGED
@@ -5,7 +5,105 @@ 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.3.2] - 2025-01-03
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
+
57
+ ## [4.4.0] - 2026-02-06
58
+
59
+ - Android SDK version: 18.0.1
60
+ - iOS SDK version: 6.13.0
61
+
62
+ ### React Native
63
+
64
+ #### Added
65
+
66
+ - Added cache for freeRASP callbacks when listener is not registered with the app
67
+ - Added API for `automation` callback into `ThreatEventActions` (Android only)
68
+
69
+ #### Fixed
70
+
71
+ - Prevent multiple registration of the freeRASP listeners on the native side
72
+
73
+ #### Changed
74
+
75
+ - Updated compile and target SDK versions to 36 on Android
76
+ - Higher compileSdk from [rootProject, plugin] is now used in build.gradle on Android
77
+
78
+ ### Android
79
+
80
+ #### Added
81
+
82
+ - Added support for `KernelSU` to the existing root detection capabilities
83
+ - Added support for `HMA` to the existing root detection capabilities
84
+ - Added new malware detection capabilities
85
+ - Added `onAutomationDetected()` callback to `ThreatDetected` interface
86
+ - We are introducing a new capability, detecting whether the device is being automated using tools like Appium
87
+ - Added value restrictions to `externalId`
88
+ - Method `storeExternalId()` now returns `ExternalIdResult`, which indicates `Success` or `Error` when `externalId` violates restrictions
89
+
90
+ #### Fixed
91
+
92
+ - Fixed exception handling for the KeyStore `getEntry` operation
93
+ - Fixed issue in `ScreenProtector` concerning the `onScreenRecordingDetected` invocations
94
+ - Merged internal shared libraries into a single one, reducing the final APK size
95
+ - Fixed bug related to key storing in keystore type detection (hw-backed keystore check)
96
+ - Fixed manifest queries merge
97
+
98
+ #### Changed
99
+
100
+ - Removed unused library `tmlib`
101
+ - Refactoring of signature verification code
102
+ - Updated compile and target API to 36
103
+ - Improved root detection capabilities
104
+ - Detection of wireless ADB added to ADB detections
105
+
106
+ ## [4.3.2] - 2026-01-03
9
107
 
10
108
  - Android SDK version: 17.0.1
11
109
  - iOS SDK version: 6.13.0
@@ -44,8 +44,14 @@ def getDefault(name) {
44
44
  return project.properties["FreeraspReactNative_" + name]
45
45
  }
46
46
 
47
+ def getMaxVersion(name) {
48
+ def rootVersion = rootProject.ext.has(name) ? rootProject.ext.get(name).toInteger() : 0
49
+ def pluginVersion = getIntegerDefault(name)
50
+ return Math.max(rootVersion, pluginVersion)
51
+ }
52
+
47
53
  android {
48
- compileSdkVersion getIntegerDefault("compileSdkVersion")
54
+ compileSdk getMaxVersion("compileSdk")
49
55
 
50
56
  defaultConfig {
51
57
  minSdkVersion getIntegerDefault("minSdkVersion")
@@ -99,7 +105,7 @@ dependencies {
99
105
  implementation "com.facebook.react:react-native:$react_native_version"
100
106
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
101
107
  implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1"
102
- implementation "com.aheaditec.talsec.security:TalsecSecurity-Community-ReactNative:17.0.1"
108
+ implementation "com.aheaditec.talsec.security:TalsecSecurity-Community-ReactNative:18.0.4"
103
109
  }
104
110
 
105
111
  if (isNewArchitectureEnabled()) {
@@ -1,6 +1,6 @@
1
1
  FreeraspReactNative_kotlinVersion=2.1.0
2
2
  FreeraspReactNative_minSdkVersion=23
3
- FreeraspReactNative_targetSdkVersion=35
4
- FreeraspReactNative_compileSdkVersion=35
3
+ FreeraspReactNative_targetSdkVersion=36
4
+ FreeraspReactNative_compileSdk=36
5
5
  FreeraspReactNative_ndkversion=21.4.7075529
6
6
  FreeraspReactNative_reactNativeVersion=+
@@ -4,11 +4,11 @@ import android.os.Build
4
4
  import android.os.Handler
5
5
  import android.os.HandlerThread
6
6
  import android.os.Looper
7
+ import com.aheaditec.talsec_security.security.api.ExternalIdResult
7
8
  import com.aheaditec.talsec_security.security.api.SuspiciousAppInfo
8
9
  import com.aheaditec.talsec_security.security.api.Talsec
9
10
  import com.aheaditec.talsec_security.security.api.TalsecConfig
10
11
  import com.aheaditec.talsec_security.security.api.TalsecMode
11
- import com.aheaditec.talsec_security.security.api.ThreatListener
12
12
  import com.facebook.react.bridge.Arguments
13
13
  import com.facebook.react.bridge.LifecycleEventListener
14
14
  import com.facebook.react.bridge.Promise
@@ -18,10 +18,12 @@ import com.facebook.react.bridge.ReactMethod
18
18
  import com.facebook.react.bridge.ReadableMap
19
19
  import com.facebook.react.bridge.UiThreadUtil.runOnUiThread
20
20
  import com.facebook.react.bridge.WritableArray
21
+ import com.facebook.react.bridge.WritableMap
21
22
  import com.facebook.react.modules.core.DeviceEventManagerModule
22
- import com.freeraspreactnative.events.BaseRaspEvent
23
23
  import com.freeraspreactnative.events.RaspExecutionStateEvent
24
24
  import com.freeraspreactnative.events.ThreatEvent
25
+ import com.freeraspreactnative.interfaces.PluginExecutionStateListener
26
+ import com.freeraspreactnative.interfaces.PluginThreatListener
25
27
  import com.freeraspreactnative.utils.Utils
26
28
  import com.freeraspreactnative.utils.getArraySafe
27
29
  import com.freeraspreactnative.utils.getBooleanSafe
@@ -33,18 +35,26 @@ import com.freeraspreactnative.utils.toEncodedWritableArray
33
35
  class FreeraspReactNativeModule(private val reactContext: ReactApplicationContext) :
34
36
  ReactContextBaseJavaModule(reactContext) {
35
37
 
36
- private val listener = ThreatListener(FreeraspThreatHandler, FreeraspThreatHandler, FreeraspThreatHandler)
37
38
  private val lifecycleListener = object : LifecycleEventListener {
38
39
  override fun onHostResume() {
40
+ PluginThreatHandler.threatDispatcher.onResume()
41
+ PluginThreatHandler.executionStateDispatcher.onResume()
39
42
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
40
43
  reactContext.currentActivity?.let { ScreenProtector.register(it) }
41
44
  }
42
45
  }
43
46
 
44
47
  override fun onHostPause() {
48
+ PluginThreatHandler.threatDispatcher.onPause()
49
+ PluginThreatHandler.executionStateDispatcher.onPause()
45
50
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
46
51
  reactContext.currentActivity?.let { ScreenProtector.unregister(it) }
47
52
  }
53
+ if (reactContext.currentActivity?.isFinishing == true) {
54
+ PluginThreatHandler.threatDispatcher.unregisterListener()
55
+ PluginThreatHandler.executionStateDispatcher.unregisterListener()
56
+ PluginThreatHandler.unregisterSDKListener(reactContext)
57
+ }
48
58
  }
49
59
 
50
60
  override fun onHostDestroy() {
@@ -57,20 +67,23 @@ class FreeraspReactNativeModule(private val reactContext: ReactApplicationContex
57
67
  }
58
68
 
59
69
  init {
60
- appReactContext = reactContext
61
70
  reactContext.addLifecycleEventListener(lifecycleListener)
62
71
  initializeEventKeys()
72
+ PluginThreatHandler.initializeDispatchers(PluginListener(reactContext))
63
73
  }
64
74
 
65
75
  @ReactMethod
66
76
  fun talsecStart(
67
77
  options: ReadableMap, promise: Promise
68
78
  ) {
79
+ if (talsecStarted) {
80
+ promise.resolve("freeRASP started")
81
+ return
82
+ }
69
83
 
70
84
  try {
71
85
  val config = buildTalsecConfig(options)
72
- FreeraspThreatHandler.listener = ThreatListener
73
- listener.registerListener(reactContext)
86
+ PluginThreatHandler.registerSDKListener(reactContext)
74
87
  runOnUiThread {
75
88
  Talsec.start(reactContext, config, TalsecMode.BACKGROUND)
76
89
  mainHandler.post {
@@ -147,13 +160,30 @@ class FreeraspReactNativeModule(private val reactContext: ReactApplicationContex
147
160
  }
148
161
 
149
162
  @ReactMethod
150
- fun addListener(@Suppress("UNUSED_PARAMETER") eventName: String) {
151
- // Set up any upstream listeners or background tasks as necessary
163
+ fun addListener(eventName: String) {
164
+ if (eventName == ThreatEvent.CHANNEL_NAME) {
165
+ PluginThreatHandler.threatDispatcher.registerListener()
166
+ }
167
+ if (eventName == RaspExecutionStateEvent.CHANNEL_NAME) {
168
+ PluginThreatHandler.executionStateDispatcher.registerListener()
169
+ }
152
170
  }
153
171
 
154
172
  @ReactMethod
155
173
  fun removeListeners(@Suppress("UNUSED_PARAMETER") count: Int) {
156
- // Remove upstream listeners, stop unnecessary background tasks
174
+ // built-in RN method, however it does not suit us as it just tells
175
+ // number of un-registered listeners, so we use `removeListenerForEvent`
176
+ }
177
+
178
+ @ReactMethod
179
+ fun removeListenerForEvent(eventName: String, promise: Promise) {
180
+ if (eventName == ThreatEvent.CHANNEL_NAME) {
181
+ PluginThreatHandler.threatDispatcher.unregisterListener()
182
+ }
183
+ if (eventName == RaspExecutionStateEvent.CHANNEL_NAME) {
184
+ PluginThreatHandler.executionStateDispatcher.unregisterListener()
185
+ }
186
+ promise.resolve("Listener unregistered")
157
187
  }
158
188
 
159
189
  /**
@@ -218,17 +248,41 @@ class FreeraspReactNativeModule(private val reactContext: ReactApplicationContex
218
248
 
219
249
  @ReactMethod
220
250
  fun storeExternalId(
221
- externalId: String, promise: Promise
251
+ externalId: String, promise: Promise
222
252
  ) {
223
- try {
224
- Talsec.storeExternalId(reactContext, externalId)
225
- promise.resolve("OK - Store external ID")
226
- } catch (e: Exception) {
253
+ try {
254
+ when (val result = Talsec.storeExternalId(reactContext, externalId)) {
255
+ is ExternalIdResult.Error -> {
227
256
  promise.reject(
228
- "NativePluginError",
229
- "Error during storeExternalId operation in Talsec Native Plugin"
257
+ "ExternalIdError",
258
+ "Setting up External ID failed - ${result.errorMsg}"
230
259
  )
260
+ }
261
+
262
+ is ExternalIdResult.Success -> {
263
+ promise.resolve("OK - Store external ID")
264
+ return
265
+ }
231
266
  }
267
+ } catch (e: Exception) {
268
+ promise.reject(
269
+ "NativePluginError",
270
+ "Error during storeExternalId operation in Talsec Native Plugin"
271
+ )
272
+ }
273
+ }
274
+
275
+ @ReactMethod
276
+ fun removeExternalId(promise: Promise) {
277
+ try {
278
+ Talsec.removeExternalId(reactContext)
279
+ promise.resolve("OK - External ID removed")
280
+ } catch (e: Exception) {
281
+ promise.reject(
282
+ "NativePluginError",
283
+ "Error during storeExternalId operation in Talsec Native Plugin"
284
+ )
285
+ }
232
286
  }
233
287
 
234
288
  private fun buildTalsecConfig(config: ReadableMap): TalsecConfig {
@@ -260,51 +314,41 @@ class FreeraspReactNativeModule(private val reactContext: ReactApplicationContex
260
314
  private val backgroundHandler = Handler(backgroundHandlerThread.looper)
261
315
  private val mainHandler = Handler(Looper.getMainLooper())
262
316
 
263
- private lateinit var appReactContext: ReactApplicationContext
264
-
265
317
  internal var talsecStarted = false
318
+ }
319
+
320
+ internal class PluginListener(private val reactContext: ReactApplicationContext) :
321
+ PluginThreatListener, PluginExecutionStateListener {
266
322
 
267
- private fun notifyEvent(event: BaseRaspEvent) {
323
+ override fun threatDetected(threatEventType: ThreatEvent) {
268
324
  val params = Arguments.createMap()
269
- params.putInt(event.channelKey, event.value)
270
- appReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
271
- .emit(event.channelName, params)
325
+ params.putInt(threatEventType.channelKey, threatEventType.value)
326
+ notifyEvent(ThreatEvent.CHANNEL_NAME, params)
272
327
  }
273
328
 
274
- /**
275
- * Sends malware detected event to React Native
276
- */
277
- private fun notifyMalware(suspiciousApps: MutableList<SuspiciousAppInfo>) {
278
- // Perform the malware encoding on a background thread
329
+ override fun malwareDetected(suspiciousApps: MutableList<SuspiciousAppInfo>) {
279
330
  backgroundHandler.post {
280
-
281
- val encodedSuspiciousApps = suspiciousApps.toEncodedWritableArray(appReactContext)
282
-
331
+ val encodedSuspiciousApps = suspiciousApps.toEncodedWritableArray(reactContext)
283
332
  mainHandler.post {
284
333
  val params = Arguments.createMap()
285
334
  params.putInt(ThreatEvent.CHANNEL_KEY, ThreatEvent.Malware.value)
286
335
  params.putArray(
287
336
  ThreatEvent.MALWARE_CHANNEL_KEY, encodedSuspiciousApps
288
337
  )
289
-
290
- appReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
291
- .emit(ThreatEvent.CHANNEL_NAME, params)
338
+ notifyEvent(ThreatEvent.CHANNEL_NAME, params)
292
339
  }
293
340
  }
294
341
  }
295
- }
296
-
297
- internal object ThreatListener : FreeraspThreatHandler.TalsecReactNative {
298
- override fun threatDetected(threatEventType: ThreatEvent) {
299
- notifyEvent(threatEventType)
300
- }
301
342
 
302
- override fun malwareDetected(suspiciousApps: MutableList<SuspiciousAppInfo>) {
303
- notifyMalware(suspiciousApps)
343
+ override fun raspExecutionStateChanged(event: RaspExecutionStateEvent) {
344
+ val params = Arguments.createMap()
345
+ params.putInt(event.channelKey, event.value)
346
+ notifyEvent(event.channelName, params)
304
347
  }
305
348
 
306
- override fun raspExecutionStateChanged(event: RaspExecutionStateEvent) {
307
- notifyEvent(event)
349
+ private fun notifyEvent(eventName: String, params: WritableMap) {
350
+ reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
351
+ .emit(eventName, params)
308
352
  }
309
353
  }
310
354
  }
@@ -0,0 +1,126 @@
1
+ package com.freeraspreactnative
2
+
3
+ import android.content.Context
4
+ import com.aheaditec.talsec_security.security.api.SuspiciousAppInfo
5
+ import com.aheaditec.talsec_security.security.api.ThreatListener
6
+ import com.freeraspreactnative.dispatchers.ExecutionStateDispatcher
7
+ import com.freeraspreactnative.dispatchers.ThreatDispatcher
8
+ import com.freeraspreactnative.events.RaspExecutionStateEvent
9
+ import com.freeraspreactnative.events.ThreatEvent
10
+
11
+ internal object PluginThreatHandler {
12
+
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
+ }
20
+
21
+ private val threatDetected = object : ThreatListener.ThreatDetected() {
22
+
23
+ override fun onRootDetected() {
24
+ threatDispatcher.dispatchThreat(ThreatEvent.PrivilegedAccess)
25
+ }
26
+
27
+ override fun onDebuggerDetected() {
28
+ threatDispatcher.dispatchThreat(ThreatEvent.Debug)
29
+ }
30
+
31
+ override fun onEmulatorDetected() {
32
+ threatDispatcher.dispatchThreat(ThreatEvent.Simulator)
33
+ }
34
+
35
+ override fun onTamperDetected() {
36
+ threatDispatcher.dispatchThreat(ThreatEvent.AppIntegrity)
37
+ }
38
+
39
+ override fun onUntrustedInstallationSourceDetected() {
40
+ threatDispatcher.dispatchThreat(ThreatEvent.UnofficialStore)
41
+ }
42
+
43
+ override fun onHookDetected() {
44
+ threatDispatcher.dispatchThreat(ThreatEvent.Hooks)
45
+ }
46
+
47
+ override fun onDeviceBindingDetected() {
48
+ threatDispatcher.dispatchThreat(ThreatEvent.DeviceBinding)
49
+ }
50
+
51
+ override fun onObfuscationIssuesDetected() {
52
+ threatDispatcher.dispatchThreat(ThreatEvent.ObfuscationIssues)
53
+ }
54
+
55
+ override fun onMalwareDetected(suspiciousAppInfos: MutableList<SuspiciousAppInfo>) {
56
+ threatDispatcher.dispatchMalware(suspiciousAppInfos ?: mutableListOf())
57
+ }
58
+
59
+ override fun onScreenshotDetected() {
60
+ threatDispatcher.dispatchThreat(ThreatEvent.Screenshot)
61
+ }
62
+
63
+ override fun onScreenRecordingDetected() {
64
+ threatDispatcher.dispatchThreat(ThreatEvent.ScreenRecording)
65
+ }
66
+
67
+ override fun onMultiInstanceDetected() {
68
+ threatDispatcher.dispatchThreat(ThreatEvent.MultiInstance)
69
+ }
70
+
71
+ override fun onUnsecureWifiDetected() {
72
+ threatDispatcher.dispatchThreat(ThreatEvent.UnsecureWifi)
73
+ }
74
+
75
+ override fun onTimeSpoofingDetected() {
76
+ threatDispatcher.dispatchThreat(ThreatEvent.TimeSpoofing)
77
+ }
78
+
79
+ override fun onLocationSpoofingDetected() {
80
+ threatDispatcher.dispatchThreat(ThreatEvent.LocationSpoofing)
81
+ }
82
+
83
+ override fun onAutomationDetected() {
84
+ threatDispatcher.dispatchThreat(ThreatEvent.Automation)
85
+ }
86
+ }
87
+
88
+ private val deviceState = object : ThreatListener.DeviceState() {
89
+
90
+ override fun onUnlockedDeviceDetected() {
91
+ threatDispatcher.dispatchThreat(ThreatEvent.Passcode)
92
+ }
93
+
94
+ override fun onHardwareBackedKeystoreNotAvailableDetected() {
95
+ threatDispatcher.dispatchThreat(ThreatEvent.SecureHardwareNotAvailable)
96
+ }
97
+
98
+ override fun onDeveloperModeDetected() {
99
+ threatDispatcher.dispatchThreat(ThreatEvent.DevMode)
100
+ }
101
+
102
+ override fun onADBEnabledDetected() {
103
+ threatDispatcher.dispatchThreat(ThreatEvent.ADBEnabled)
104
+ }
105
+
106
+ override fun onSystemVPNDetected() {
107
+ threatDispatcher.dispatchThreat(ThreatEvent.SystemVPN)
108
+ }
109
+ }
110
+
111
+ private val raspExecutionState = object : ThreatListener.RaspExecutionState() {
112
+ override fun onAllChecksFinished() {
113
+ executionStateDispatcher.dispatch(RaspExecutionStateEvent.AllChecksFinished)
114
+ }
115
+ }
116
+
117
+ private val internalListener = ThreatListener(threatDetected, deviceState, raspExecutionState)
118
+
119
+ internal fun registerSDKListener(context: Context) {
120
+ internalListener.registerListener(context)
121
+ }
122
+
123
+ internal fun unregisterSDKListener(context: Context) {
124
+ internalListener.unregisterListener(context)
125
+ }
126
+ }
@@ -0,0 +1,53 @@
1
+ package com.freeraspreactnative.dispatchers
2
+
3
+ import com.freeraspreactnative.events.RaspExecutionStateEvent
4
+ import com.freeraspreactnative.interfaces.PluginExecutionStateListener
5
+
6
+ internal class ExecutionStateDispatcher(private val listener: PluginExecutionStateListener) {
7
+ private val cache = mutableSetOf<RaspExecutionStateEvent>()
8
+
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()
27
+ }
28
+ }
29
+
30
+ fun onPause() {
31
+ isAppInForeground = false
32
+ }
33
+
34
+ fun dispatch(event: RaspExecutionStateEvent) {
35
+ if (isAppInForeground && isListenerRegistered) {
36
+ listener.raspExecutionStateChanged(event)
37
+ } else {
38
+ synchronized(cache) {
39
+ cache.add(event)
40
+ }
41
+ }
42
+ }
43
+
44
+ private fun flushCache() {
45
+ val events = synchronized(cache) {
46
+ val snapshot = cache.toSet()
47
+ cache.clear()
48
+ snapshot
49
+ }
50
+ events.forEach { listener.raspExecutionStateChanged(it) }
51
+ }
52
+ }
53
+
@@ -0,0 +1,75 @@
1
+ package com.freeraspreactnative.dispatchers
2
+
3
+ import com.aheaditec.talsec_security.security.api.SuspiciousAppInfo
4
+ import com.freeraspreactnative.events.ThreatEvent
5
+ import com.freeraspreactnative.interfaces.PluginThreatListener
6
+
7
+ internal class ThreatDispatcher(private val listener: PluginThreatListener) {
8
+ private val threatCache = mutableSetOf<ThreatEvent>()
9
+ private val malwareCache = mutableSetOf<SuspiciousAppInfo>()
10
+
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()
29
+ }
30
+ }
31
+
32
+ fun onPause() {
33
+ isAppInForeground = false
34
+ }
35
+
36
+ fun dispatchThreat(event: ThreatEvent) {
37
+ if (isAppInForeground && isListenerRegistered) {
38
+ listener.threatDetected(event)
39
+ } else {
40
+ synchronized(threatCache) {
41
+ threatCache.add(event)
42
+ }
43
+ }
44
+ }
45
+
46
+ fun dispatchMalware(apps: MutableList<SuspiciousAppInfo>) {
47
+ if (isAppInForeground && isListenerRegistered) {
48
+ listener.malwareDetected(apps)
49
+ }
50
+ else {
51
+ synchronized(malwareCache) {
52
+ malwareCache.addAll(apps)
53
+ }
54
+ }
55
+ }
56
+
57
+ private fun flushCache() {
58
+ val threats = synchronized(threatCache) {
59
+ val snapshot = threatCache.toSet()
60
+ threatCache.clear()
61
+ snapshot
62
+ }
63
+ threats.forEach { listener.threatDetected(it) }
64
+
65
+ val malware = synchronized(malwareCache) {
66
+ val snapshot = malwareCache.toMutableList()
67
+ malwareCache.clear()
68
+ snapshot
69
+ }
70
+ if (malware.isNotEmpty()) {
71
+ listener.malwareDetected(malware)
72
+ }
73
+ }
74
+ }
75
+
@@ -34,6 +34,7 @@ internal sealed class ThreatEvent(override val value: Int) : BaseRaspEvent {
34
34
  data object TimeSpoofing : ThreatEvent(RandomGenerator.next())
35
35
  data object LocationSpoofing : ThreatEvent(RandomGenerator.next())
36
36
  data object UnsecureWifi : ThreatEvent(RandomGenerator.next())
37
+ data object Automation : ThreatEvent(RandomGenerator.next())
37
38
 
38
39
  companion object {
39
40
  internal val CHANNEL_NAME = RandomGenerator.next().toString()
@@ -61,7 +62,8 @@ internal sealed class ThreatEvent(override val value: Int) : BaseRaspEvent {
61
62
  MultiInstance,
62
63
  TimeSpoofing,
63
64
  LocationSpoofing,
64
- UnsecureWifi
65
+ UnsecureWifi,
66
+ Automation
65
67
  ).map { it.value })
66
68
  }
67
69
  }
@@ -0,0 +1,7 @@
1
+ package com.freeraspreactnative.interfaces
2
+
3
+ import com.freeraspreactnative.events.RaspExecutionStateEvent
4
+
5
+ internal interface PluginExecutionStateListener {
6
+ fun raspExecutionStateChanged(event: RaspExecutionStateEvent)
7
+ }
@@ -0,0 +1,9 @@
1
+ package com.freeraspreactnative.interfaces
2
+
3
+ import com.aheaditec.talsec_security.security.api.SuspiciousAppInfo
4
+ import com.freeraspreactnative.events.ThreatEvent
5
+
6
+ internal interface PluginThreatListener {
7
+ fun threatDetected(threatEventType: ThreatEvent)
8
+ fun malwareDetected(suspiciousApps: MutableList<SuspiciousAppInfo>)
9
+ }
@@ -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) =>
@@ -251,6 +251,16 @@ const App = () => {
251
251
  )
252
252
  );
253
253
  },
254
+ // Android only
255
+ automation: () => {
256
+ setAppChecks((currentState) =>
257
+ currentState.map((threat) =>
258
+ threat.name === 'Automation'
259
+ ? { ...threat, status: 'nok' }
260
+ : threat
261
+ )
262
+ );
263
+ },
254
264
  };
255
265
 
256
266
  const raspExecutionStateActions = {