capacitor-freerasp 2.3.0 → 2.4.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 (34) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/CapacitorFreerasp.podspec +5 -1
  3. package/android/build.gradle +3 -3
  4. package/android/src/main/java/com/aheaditec/freerasp/FreeraspPlugin.kt +87 -24
  5. package/android/src/main/java/com/aheaditec/freerasp/PluginThreatHandler.kt +121 -0
  6. package/android/src/main/java/com/aheaditec/freerasp/dispatchers/ExecutionStateDispatcher.kt +38 -0
  7. package/android/src/main/java/com/aheaditec/freerasp/dispatchers/ThreatDispatcher.kt +62 -0
  8. package/android/src/main/java/com/aheaditec/freerasp/events/ThreatEvent.kt +3 -1
  9. package/android/src/main/java/com/aheaditec/freerasp/interfaces/PluginExecutionStateListener.kt +7 -0
  10. package/android/src/main/java/com/aheaditec/freerasp/interfaces/PluginThreatListener.kt +9 -0
  11. package/dist/esm/api/listeners/raspExecutionState.d.ts +1 -0
  12. package/dist/esm/api/listeners/raspExecutionState.js +18 -1
  13. package/dist/esm/api/listeners/raspExecutionState.js.map +1 -1
  14. package/dist/esm/api/listeners/threat.d.ts +1 -0
  15. package/dist/esm/api/listeners/threat.js +22 -2
  16. package/dist/esm/api/listeners/threat.js.map +1 -1
  17. package/dist/esm/api/methods/native.d.ts +1 -0
  18. package/dist/esm/api/methods/native.js +4 -0
  19. package/dist/esm/api/methods/native.js.map +1 -1
  20. package/dist/esm/models/threat.d.ts +1 -0
  21. package/dist/esm/models/threat.js +2 -0
  22. package/dist/esm/models/threat.js.map +1 -1
  23. package/dist/esm/types/types.d.ts +4 -0
  24. package/dist/esm/types/types.js.map +1 -1
  25. package/dist/plugin.cjs.js +49 -3
  26. package/dist/plugin.cjs.js.map +1 -1
  27. package/dist/plugin.js +49 -3
  28. package/dist/plugin.js.map +1 -1
  29. package/ios/Plugin/FreeraspPlugin.m +1 -0
  30. package/ios/Plugin/FreeraspPlugin.swift +16 -32
  31. package/ios/Plugin/dispatchers/ExecutionStateDispatcher.swift +35 -0
  32. package/ios/Plugin/dispatchers/ThreatDispatcher.swift +36 -0
  33. package/package.json +1 -1
  34. package/android/src/main/java/com/aheaditec/freerasp/ThreatHandler.kt +0 -94
package/CHANGELOG.md CHANGED
@@ -5,6 +5,65 @@ 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
+ ## [2.4.1] - 2026-02-13
9
+
10
+ - Android SDK version: 18.0.2
11
+ - iOS SDK version: 6.13.0
12
+
13
+ ### Capacitor
14
+
15
+ #### Fixed
16
+
17
+ - Resolved potential NullPointerException when execution state events are being sent
18
+
19
+ ## [2.4.0] - 2026-02-13
20
+
21
+ - Android SDK version: 18.0.2
22
+ - iOS SDK version: 6.13.0
23
+
24
+ ### Capacitor
25
+
26
+ #### Added
27
+
28
+ - Added cache for freeRASP callbacks when listener is not registered with the app
29
+ - Added API for `automation` callback into `ThreatEventActions` (Android only)
30
+
31
+ #### Fixed
32
+
33
+ - Prevent multiple registration of the freeRASP listeners on the native side
34
+
35
+ #### Changed
36
+
37
+ - Updated compile and target SDK versions to 36 on Android
38
+
39
+ ### Android
40
+
41
+ #### Added
42
+
43
+ - Added support for `KernelSU` to the existing root detection capabilities
44
+ - Added support for `HMA` to the existing root detection capabilities
45
+ - Added new malware detection capabilities
46
+ - Added `onAutomationDetected()` callback to `ThreatDetected` interface
47
+ - We are introducing a new capability, detecting whether the device is being automated using tools like Appium
48
+ - Added value restrictions to `externalId`
49
+ - Method `storeExternalId()` now returns `ExternalIdResult`, which indicates `Success` or `Error` when `externalId` violates restrictions
50
+
51
+ #### Fixed
52
+
53
+ - Fixed exception handling for the KeyStore `getEntry` operation
54
+ - Fixed issue in `ScreenProtector` concerning the `onScreenRecordingDetected` invocations
55
+ - Merged internal shared libraries into a single one, reducing the final APK size
56
+ - Fixed bug related to key storing in keystore type detection (hw-backed keystore check)
57
+ - Fixed manifest queries merge
58
+
59
+ #### Changed
60
+
61
+ - Removed unused library `tmlib`
62
+ - Refactoring of signature verification code
63
+ - Updated compile and target API to 36
64
+ - Improved root detection capabilities
65
+ - Detection of wireless ADB added to ADB detections
66
+
8
67
  ## [2.3.0] - 2025-12-15
9
68
 
10
69
  - Android SDK version: 17.0.1
@@ -10,7 +10,11 @@ Pod::Spec.new do |s|
10
10
  s.homepage = package['repository']['url']
11
11
  s.author = package['author']
12
12
  s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13
- s.source_files = 'ios/Plugin/models/*.{swift,h,m,c,cc,mm,cpp}', 'ios/Plugin/utils/*.{swift,h,m,c,cc,mm,cpp}', 'ios/Plugin/*.{swift,h,m,c,cc,mm,cpp}', 'ios/Plugin/TalsecRuntime.xcframework'
13
+ s.source_files = 'ios/Plugin/models/*.{swift,h,m,c,cc,mm,cpp}',
14
+ 'ios/Plugin/utils/*.{swift,h,m,c,cc,mm,cpp}',
15
+ 'ios/Plugin/dispatchers/*.{swift,h,m,c,cc,mm,cpp}',
16
+ 'ios/Plugin/*.{swift,h,m,c,cc,mm,cpp}',
17
+ 'ios/Plugin/TalsecRuntime.xcframework'
14
18
  s.ios.deployment_target = '13.0'
15
19
  s.dependency 'Capacitor'
16
20
  s.swift_version = '5.1'
@@ -27,10 +27,10 @@ apply plugin: 'kotlinx-serialization'
27
27
 
28
28
  android {
29
29
  namespace "com.aheaditec.freerasp"
30
- compileSdk 35
30
+ compileSdk Math.max(36, project.hasProperty('rootProject.ext.compileSdk') ? rootProject.ext.compileSdk as int : 36)
31
31
  defaultConfig {
32
32
  minSdkVersion 23
33
- targetSdkVersion 35
33
+ targetSdkVersion 36
34
34
  versionCode 1
35
35
  versionName "1.0"
36
36
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -76,5 +76,5 @@ dependencies {
76
76
  androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
77
77
  androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
78
78
 
79
- implementation 'com.aheaditec.talsec.security:TalsecSecurity-Community-Capacitor:17.0.1'
79
+ implementation 'com.aheaditec.talsec.security:TalsecSecurity-Community-Capacitor:18.0.2'
80
80
  }
@@ -1,5 +1,6 @@
1
1
  package com.aheaditec.freerasp
2
2
 
3
+ import android.content.Context
3
4
  import android.os.Build
4
5
  import android.os.Handler
5
6
  import android.os.HandlerThread
@@ -11,10 +12,11 @@ import com.aheaditec.freerasp.utils.toEncodedJSArray
11
12
  import com.aheaditec.talsec_security.security.api.SuspiciousAppInfo
12
13
  import com.aheaditec.talsec_security.security.api.Talsec
13
14
  import com.aheaditec.talsec_security.security.api.TalsecConfig
14
- import com.aheaditec.talsec_security.security.api.ThreatListener
15
15
  import com.aheaditec.freerasp.events.BaseRaspEvent
16
16
  import com.aheaditec.freerasp.events.RaspExecutionStateEvent
17
17
  import com.aheaditec.freerasp.events.ThreatEvent
18
+ import com.aheaditec.freerasp.interfaces.PluginExecutionStateListener
19
+ import com.aheaditec.freerasp.interfaces.PluginThreatListener
18
20
  import com.getcapacitor.JSObject
19
21
  import com.getcapacitor.Plugin
20
22
  import com.getcapacitor.PluginCall
@@ -22,13 +24,18 @@ import com.getcapacitor.PluginMethod
22
24
  import com.getcapacitor.annotation.CapacitorPlugin
23
25
  import org.json.JSONArray
24
26
 
27
+ typealias CapacitorCallback = (String, JSObject) -> Unit
28
+
25
29
  @CapacitorPlugin(name = "Freerasp")
26
30
  class FreeraspPlugin : Plugin() {
27
31
 
28
- private val threatHandler = TalsecThreatHandler(this)
29
- private val listener = ThreatListener(threatHandler, threatHandler, threatHandler)
30
32
  private var registered = true
31
33
 
34
+ override fun load() {
35
+ initializeEventKeys()
36
+ super.load()
37
+ }
38
+
32
39
  @PluginMethod
33
40
  fun talsecStart(call: PluginCall) {
34
41
  val config = call.getObject("config")
@@ -38,7 +45,15 @@ class FreeraspPlugin : Plugin() {
38
45
  }
39
46
  try {
40
47
  val talsecConfig = buildTalsecConfigThrowing(config)
41
- listener.registerListener(context)
48
+
49
+ val pluginCallback: CapacitorCallback = { eventName, data ->
50
+ notifyListeners(eventName, data, true)
51
+ }
52
+
53
+ PluginThreatHandler.threatDispatcher.listener = PluginListener(context, pluginCallback)
54
+ PluginThreatHandler.executionStateDispatcher.listener = PluginListener(context, pluginCallback)
55
+ PluginThreatHandler.registerListener(context)
56
+
42
57
  bridge.activity.runOnUiThread {
43
58
  Talsec.start(context, talsecConfig)
44
59
  mainHandler.post {
@@ -70,8 +85,10 @@ class FreeraspPlugin : Plugin() {
70
85
  override fun handleOnPause() {
71
86
  super.handleOnPause()
72
87
  if (activity.isFinishing) {
73
- listener.unregisterListener(context)
88
+ PluginThreatHandler.unregisterListener(context)
74
89
  registered = false
90
+ PluginThreatHandler.threatDispatcher.listener = null
91
+ PluginThreatHandler.executionStateDispatcher.listener = null
75
92
  }
76
93
  }
77
94
 
@@ -79,7 +96,7 @@ class FreeraspPlugin : Plugin() {
79
96
  super.handleOnResume()
80
97
  if (!registered) {
81
98
  registered = true
82
- listener.registerListener(context)
99
+ PluginThreatHandler.registerListener(context)
83
100
  }
84
101
  }
85
102
 
@@ -95,6 +112,12 @@ class FreeraspPlugin : Plugin() {
95
112
  backgroundHandlerThread.quitSafely()
96
113
  }
97
114
 
115
+ // Trigger lazy initialization of the freeRASP events
116
+ private fun initializeEventKeys() {
117
+ ThreatEvent.ALL_EVENTS
118
+ RaspExecutionStateEvent.ALL_EVENTS
119
+ }
120
+
98
121
  /**
99
122
  * Method to get the random identifiers of callbacks
100
123
  */
@@ -129,15 +152,15 @@ class FreeraspPlugin : Plugin() {
129
152
  * Method to setup the execution state message passing between native and Capacitor
130
153
  * @return list of [CHANNEL_NAME, CHANNEL_KEY]
131
154
  */
132
- @PluginMethod
133
- fun getRaspExecutionStateChannelData(call: PluginCall) {
155
+ @PluginMethod
156
+ fun getRaspExecutionStateChannelData(call: PluginCall) {
134
157
  val channelData = JSONArray(
135
158
  (listOf(
136
159
  RaspExecutionStateEvent.CHANNEL_NAME, RaspExecutionStateEvent.CHANNEL_KEY
137
160
  ))
138
161
  )
139
162
  call.resolve(JSObject().put("ids", channelData))
140
- }
163
+ }
141
164
 
142
165
  /**
143
166
  * We never send an invalid callback over our channel.
@@ -253,21 +276,17 @@ class FreeraspPlugin : Plugin() {
253
276
  }
254
277
  }
255
278
 
256
- internal fun notifyListeners(event: BaseRaspEvent) {
257
- notifyListeners(event.channelName, JSObject().put(event.channelKey, event.value), true)
258
- }
259
-
260
- internal fun notifyMalware(suspiciousApps: MutableList<SuspiciousAppInfo>) {
261
- // Perform the malware encoding on a background thread
262
- backgroundHandler.post {
263
-
264
- val encodedSuspiciousApps = suspiciousApps.toEncodedJSArray(context)
265
- mainHandler.post {
266
- val params = JSObject()
267
- .put(ThreatEvent.CHANNEL_KEY, ThreatEvent.Malware.value)
268
- .put(ThreatEvent.MALWARE_CHANNEL_KEY, encodedSuspiciousApps)
269
- notifyListeners(ThreatEvent.CHANNEL_NAME, params, true)
270
- }
279
+ @PluginMethod
280
+ fun removeExternalId(call: PluginCall) {
281
+ try {
282
+ Talsec.removeExternalId(context)
283
+ call.resolve(JSObject().put("result", true))
284
+ } catch (e: Exception) {
285
+ call.reject(
286
+ "Error during removeExternalId operation in freeRASP Native Plugin",
287
+ "NativePluginError"
288
+ )
289
+ return
271
290
  }
272
291
  }
273
292
 
@@ -298,5 +317,49 @@ class FreeraspPlugin : Plugin() {
298
317
  private val mainHandler = Handler(Looper.getMainLooper())
299
318
 
300
319
  internal var talsecStarted = false
320
+
321
+ internal fun notifyEvent(
322
+ event: BaseRaspEvent,
323
+ notifyListenersCallback: CapacitorCallback
324
+ ) {
325
+ val params = JSObject().put(event.channelKey, event.value)
326
+ notifyListenersCallback(event.channelName, params)
327
+ }
328
+
329
+ internal fun notifyMalware(
330
+ suspiciousApps: MutableList<SuspiciousAppInfo>,
331
+ context: Context,
332
+ notifyListenersCallback: CapacitorCallback
333
+ ) {
334
+ // Perform the malware encoding on a background thread
335
+ backgroundHandler.post {
336
+
337
+ val encodedSuspiciousApps = suspiciousApps.toEncodedJSArray(context)
338
+ mainHandler.post {
339
+ val params = JSObject()
340
+ .put(ThreatEvent.CHANNEL_KEY, ThreatEvent.Malware.value)
341
+ .put(ThreatEvent.MALWARE_CHANNEL_KEY, encodedSuspiciousApps)
342
+ notifyListenersCallback.invoke(ThreatEvent.CHANNEL_NAME, params)
343
+ }
344
+
345
+ }
346
+ }
347
+ }
348
+
349
+ internal class PluginListener(
350
+ private val context: Context,
351
+ private val pluginCallback: CapacitorCallback
352
+ ) : PluginThreatListener, PluginExecutionStateListener {
353
+ override fun threatDetected(threatEventType: ThreatEvent) {
354
+ notifyEvent(threatEventType, pluginCallback)
355
+ }
356
+
357
+ override fun malwareDetected(suspiciousApps: MutableList<SuspiciousAppInfo>) {
358
+ notifyMalware(suspiciousApps, context, pluginCallback)
359
+ }
360
+
361
+ override fun raspExecutionStateChanged(event: RaspExecutionStateEvent) {
362
+ notifyEvent(event, pluginCallback)
363
+ }
301
364
  }
302
365
  }
@@ -0,0 +1,121 @@
1
+ package com.aheaditec.freerasp
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.aheaditec.freerasp.dispatchers.ExecutionStateDispatcher
7
+ import com.aheaditec.freerasp.dispatchers.ThreatDispatcher
8
+ import com.aheaditec.freerasp.events.RaspExecutionStateEvent
9
+ import com.aheaditec.freerasp.events.ThreatEvent
10
+
11
+ internal object PluginThreatHandler {
12
+
13
+ internal val threatDispatcher = ThreatDispatcher()
14
+ internal val executionStateDispatcher = ExecutionStateDispatcher()
15
+
16
+ private val threatDetected = object : ThreatListener.ThreatDetected() {
17
+
18
+ override fun onRootDetected() {
19
+ threatDispatcher.dispatchThreat(ThreatEvent.PrivilegedAccess)
20
+ }
21
+
22
+ override fun onDebuggerDetected() {
23
+ threatDispatcher.dispatchThreat(ThreatEvent.Debug)
24
+ }
25
+
26
+ override fun onEmulatorDetected() {
27
+ threatDispatcher.dispatchThreat(ThreatEvent.Simulator)
28
+ }
29
+
30
+ override fun onTamperDetected() {
31
+ threatDispatcher.dispatchThreat(ThreatEvent.AppIntegrity)
32
+ }
33
+
34
+ override fun onUntrustedInstallationSourceDetected() {
35
+ threatDispatcher.dispatchThreat(ThreatEvent.UnofficialStore)
36
+ }
37
+
38
+ override fun onHookDetected() {
39
+ threatDispatcher.dispatchThreat(ThreatEvent.Hooks)
40
+ }
41
+
42
+ override fun onDeviceBindingDetected() {
43
+ threatDispatcher.dispatchThreat(ThreatEvent.DeviceBinding)
44
+ }
45
+
46
+ override fun onObfuscationIssuesDetected() {
47
+ threatDispatcher.dispatchThreat(ThreatEvent.ObfuscationIssues)
48
+ }
49
+
50
+ override fun onMalwareDetected(suspiciousAppInfos: MutableList<SuspiciousAppInfo>) {
51
+ threatDispatcher.dispatchMalware(suspiciousAppInfos ?: mutableListOf())
52
+ }
53
+
54
+ override fun onScreenshotDetected() {
55
+ threatDispatcher.dispatchThreat(ThreatEvent.Screenshot)
56
+ }
57
+
58
+ override fun onScreenRecordingDetected() {
59
+ threatDispatcher.dispatchThreat(ThreatEvent.ScreenRecording)
60
+ }
61
+
62
+ override fun onMultiInstanceDetected() {
63
+ threatDispatcher.dispatchThreat(ThreatEvent.MultiInstance)
64
+ }
65
+
66
+ override fun onUnsecureWifiDetected() {
67
+ threatDispatcher.dispatchThreat(ThreatEvent.UnsecureWifi)
68
+ }
69
+
70
+ override fun onTimeSpoofingDetected() {
71
+ threatDispatcher.dispatchThreat(ThreatEvent.TimeSpoofing)
72
+ }
73
+
74
+ override fun onLocationSpoofingDetected() {
75
+ threatDispatcher.dispatchThreat(ThreatEvent.LocationSpoofing)
76
+ }
77
+
78
+ override fun onAutomationDetected() {
79
+ threatDispatcher.dispatchThreat(ThreatEvent.Automation)
80
+ }
81
+ }
82
+
83
+ private val deviceState = object : ThreatListener.DeviceState() {
84
+
85
+ override fun onUnlockedDeviceDetected() {
86
+ threatDispatcher.dispatchThreat(ThreatEvent.Passcode)
87
+ }
88
+
89
+ override fun onHardwareBackedKeystoreNotAvailableDetected() {
90
+ threatDispatcher.dispatchThreat(ThreatEvent.SecureHardwareNotAvailable)
91
+ }
92
+
93
+ override fun onDeveloperModeDetected() {
94
+ threatDispatcher.dispatchThreat(ThreatEvent.DevMode)
95
+ }
96
+
97
+ override fun onADBEnabledDetected() {
98
+ threatDispatcher.dispatchThreat(ThreatEvent.ADBEnabled)
99
+ }
100
+
101
+ override fun onSystemVPNDetected() {
102
+ threatDispatcher.dispatchThreat(ThreatEvent.SystemVPN)
103
+ }
104
+ }
105
+
106
+ private val raspExecutionState = object : ThreatListener.RaspExecutionState() {
107
+ override fun onAllChecksFinished() {
108
+ executionStateDispatcher.dispatch(RaspExecutionStateEvent.AllChecksFinished)
109
+ }
110
+ }
111
+
112
+ private val internalListener = ThreatListener(threatDetected, deviceState, raspExecutionState)
113
+
114
+ internal fun registerListener(context: Context) {
115
+ internalListener.registerListener(context)
116
+ }
117
+
118
+ internal fun unregisterListener(context: Context) {
119
+ internalListener.unregisterListener(context)
120
+ }
121
+ }
@@ -0,0 +1,38 @@
1
+ package com.aheaditec.freerasp.dispatchers
2
+
3
+ import com.aheaditec.freerasp.events.RaspExecutionStateEvent
4
+ import com.aheaditec.freerasp.interfaces.PluginExecutionStateListener
5
+
6
+ internal class ExecutionStateDispatcher {
7
+ private val cache = mutableSetOf<RaspExecutionStateEvent>()
8
+
9
+ var listener: PluginExecutionStateListener? = null
10
+ set(value) {
11
+ field = value
12
+ if (value != null) {
13
+ flushCache(value)
14
+ }
15
+ }
16
+
17
+ fun dispatch(event: RaspExecutionStateEvent) {
18
+ val checkedListener = synchronized(cache) {
19
+ val currentListener = listener
20
+ if (currentListener != null) {
21
+ currentListener
22
+ } else {
23
+ cache.add(event)
24
+ null
25
+ }
26
+ }
27
+ checkedListener?.raspExecutionStateChanged(event)
28
+ }
29
+
30
+ private fun flushCache(registeredListener: PluginExecutionStateListener) {
31
+ val events = synchronized(cache) {
32
+ val snapshot = cache.toSet()
33
+ cache.clear()
34
+ snapshot
35
+ }
36
+ events.forEach { registeredListener.raspExecutionStateChanged(it) }
37
+ }
38
+ }
@@ -0,0 +1,62 @@
1
+ package com.aheaditec.freerasp.dispatchers
2
+
3
+ import com.aheaditec.talsec_security.security.api.SuspiciousAppInfo
4
+ import com.aheaditec.freerasp.events.ThreatEvent
5
+ import com.aheaditec.freerasp.interfaces.PluginThreatListener
6
+
7
+ internal class ThreatDispatcher {
8
+ private val threatCache = mutableSetOf<ThreatEvent>()
9
+ private val malwareCache = mutableSetOf<SuspiciousAppInfo>()
10
+
11
+ var listener: PluginThreatListener? = null
12
+ set(value) {
13
+ field = value
14
+ if (value != null) {
15
+ flushCache(value)
16
+ }
17
+ }
18
+
19
+ fun dispatchThreat(event: ThreatEvent) {
20
+ val checkedListener = synchronized(threatCache) {
21
+ val currentListener = listener
22
+ if (currentListener != null) {
23
+ currentListener
24
+ } else {
25
+ threatCache.add(event)
26
+ null
27
+ }
28
+ }
29
+ checkedListener?.threatDetected(event)
30
+ }
31
+
32
+ fun dispatchMalware(apps: MutableList<SuspiciousAppInfo>) {
33
+ val checkedListener = synchronized(malwareCache) {
34
+ val currentListener = listener
35
+ if (currentListener != null) {
36
+ currentListener
37
+ } else {
38
+ malwareCache.addAll(apps)
39
+ null
40
+ }
41
+ }
42
+ checkedListener?.malwareDetected(apps)
43
+ }
44
+
45
+ private fun flushCache(registeredListener: PluginThreatListener) {
46
+ val threats = synchronized(threatCache) {
47
+ val snapshot = threatCache.toSet()
48
+ threatCache.clear()
49
+ snapshot
50
+ }
51
+ threats.forEach { registeredListener.threatDetected(it) }
52
+
53
+ val malware = synchronized(malwareCache) {
54
+ val snapshot = malwareCache.toMutableList()
55
+ malwareCache.clear()
56
+ snapshot
57
+ }
58
+ if (malware.isNotEmpty()) {
59
+ registeredListener.malwareDetected(malware)
60
+ }
61
+ }
62
+ }
@@ -34,6 +34,7 @@ internal sealed class ThreatEvent(override val value: Int) : BaseRaspEvent {
34
34
  object TimeSpoofing : ThreatEvent(RandomGenerator.next())
35
35
  object LocationSpoofing : ThreatEvent(RandomGenerator.next())
36
36
  object UnsecureWifi : ThreatEvent(RandomGenerator.next())
37
+ object Automation : ThreatEvent(RandomGenerator.next())
37
38
 
38
39
  companion object {
39
40
 
@@ -62,7 +63,8 @@ internal sealed class ThreatEvent(override val value: Int) : BaseRaspEvent {
62
63
  MultiInstance,
63
64
  TimeSpoofing,
64
65
  LocationSpoofing,
65
- UnsecureWifi
66
+ UnsecureWifi,
67
+ Automation
66
68
  ).map { it.value }
67
69
  )
68
70
  }
@@ -0,0 +1,7 @@
1
+ package com.aheaditec.freerasp.interfaces
2
+
3
+ import com.aheaditec.freerasp.events.RaspExecutionStateEvent
4
+
5
+ internal interface PluginExecutionStateListener {
6
+ fun raspExecutionStateChanged(event: RaspExecutionStateEvent)
7
+ }
@@ -0,0 +1,9 @@
1
+ package com.aheaditec.freerasp.interfaces
2
+
3
+ import com.aheaditec.talsec_security.security.api.SuspiciousAppInfo
4
+ import com.aheaditec.freerasp.events.ThreatEvent
5
+
6
+ internal interface PluginThreatListener {
7
+ fun threatDetected(threatEventType: ThreatEvent)
8
+ fun malwareDetected(suspiciousApps: MutableList<SuspiciousAppInfo>)
9
+ }
@@ -1,2 +1,3 @@
1
1
  import type { RaspExecutionStateEventActions } from '../../types/types';
2
2
  export declare const registerRaspExecutionStateListener: (config: RaspExecutionStateEventActions) => Promise<void>;
3
+ export declare const removeRaspExecutionStateListener: () => Promise<void>;
@@ -2,10 +2,20 @@ import { getRaspExecutionStateChannelData, prepareRaspExecutionStateMapping } fr
2
2
  import { RaspExecutionState } from '../../models/raspExecutionState';
3
3
  import { onInvalidCallback } from '../methods/native';
4
4
  import { Talsec } from '../nativeModules';
5
+ let eventsListener = null;
6
+ let isInitializing = false;
5
7
  export const registerRaspExecutionStateListener = async (config) => {
8
+ if (isInitializing) {
9
+ return;
10
+ }
11
+ isInitializing = true;
12
+ if (eventsListener) {
13
+ await eventsListener.remove();
14
+ eventsListener = null;
15
+ }
6
16
  const [channel, key] = await getRaspExecutionStateChannelData();
7
17
  await prepareRaspExecutionStateMapping();
8
- await Talsec.addListener(channel, async (event) => {
18
+ eventsListener = await Talsec.addListener(channel, async (event) => {
9
19
  var _a;
10
20
  if (event[key] == undefined) {
11
21
  onInvalidCallback();
@@ -19,5 +29,12 @@ export const registerRaspExecutionStateListener = async (config) => {
19
29
  break;
20
30
  }
21
31
  });
32
+ isInitializing = false;
33
+ };
34
+ export const removeRaspExecutionStateListener = async () => {
35
+ if (eventsListener) {
36
+ await eventsListener.remove();
37
+ eventsListener = null;
38
+ }
22
39
  };
23
40
  //# sourceMappingURL=raspExecutionState.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"raspExecutionState.js","sourceRoot":"","sources":["../../../../src/api/listeners/raspExecutionState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gCAAgC,EAAE,gCAAgC,EAAE,MAAM,mCAAmC,CAAC;AACvH,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAErE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,MAAM,CAAC,MAAM,kCAAkC,GAAG,KAAK,EAAE,MAAsC,EAAiB,EAAE;IAChH,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,MAAM,gCAAgC,EAAE,CAAC;IAChE,MAAM,gCAAgC,EAAE,CAAC;IAEzC,MAAM,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,KAAU,EAAE,EAAE;;QACrD,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,SAAS,EAAE,CAAC;YAC5B,iBAAiB,EAAE,CAAC;QACtB,CAAC;QACD,QAAQ,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YACnB,KAAK,kBAAkB,CAAC,iBAAiB,CAAC,KAAK;gBAC7C,MAAA,MAAM,CAAC,iBAAiB,sDAAI,CAAC;gBAC7B,MAAM;YACR;gBACE,iBAAiB,EAAE,CAAC;gBACpB,MAAM;QACV,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC","sourcesContent":["import { getRaspExecutionStateChannelData, prepareRaspExecutionStateMapping } from '../../channels/raspExecutionState';\nimport { RaspExecutionState } from '../../models/raspExecutionState';\nimport type { RaspExecutionStateEventActions } from '../../types/types';\nimport { onInvalidCallback } from '../methods/native';\nimport { Talsec } from '../nativeModules';\n\nexport const registerRaspExecutionStateListener = async (config: RaspExecutionStateEventActions): Promise<void> => {\n const [channel, key] = await getRaspExecutionStateChannelData();\n await prepareRaspExecutionStateMapping();\n\n await Talsec.addListener(channel, async (event: any) => {\n if (event[key] == undefined) {\n onInvalidCallback();\n }\n switch (event[key]) {\n case RaspExecutionState.AllChecksFinished.value:\n config.allChecksFinished?.();\n break;\n default:\n onInvalidCallback();\n break;\n }\n });\n};\n"]}
1
+ {"version":3,"file":"raspExecutionState.js","sourceRoot":"","sources":["../../../../src/api/listeners/raspExecutionState.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gCAAgC,EAAE,gCAAgC,EAAE,MAAM,mCAAmC,CAAC;AACvH,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAErE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,IAAI,cAAc,GAAgC,IAAI,CAAC;AACvD,IAAI,cAAc,GAAG,KAAK,CAAC;AAE3B,MAAM,CAAC,MAAM,kCAAkC,GAAG,KAAK,EAAE,MAAsC,EAAiB,EAAE;IAChH,IAAI,cAAc,EAAE,CAAC;QACnB,OAAO;IACT,CAAC;IACD,cAAc,GAAG,IAAI,CAAC;IAEtB,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,cAAc,CAAC,MAAM,EAAE,CAAC;QAC9B,cAAc,GAAG,IAAI,CAAC;IACxB,CAAC;IAED,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,MAAM,gCAAgC,EAAE,CAAC;IAChE,MAAM,gCAAgC,EAAE,CAAC;IAEzC,cAAc,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,KAAU,EAAE,EAAE;;QACtE,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,SAAS,EAAE,CAAC;YAC5B,iBAAiB,EAAE,CAAC;QACtB,CAAC;QACD,QAAQ,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YACnB,KAAK,kBAAkB,CAAC,iBAAiB,CAAC,KAAK;gBAC7C,MAAA,MAAM,CAAC,iBAAiB,sDAAI,CAAC;gBAC7B,MAAM;YACR;gBACE,iBAAiB,EAAE,CAAC;gBACpB,MAAM;QACV,CAAC;IACH,CAAC,CAAC,CAAC;IACH,cAAc,GAAG,KAAK,CAAC;AACzB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gCAAgC,GAAG,KAAK,IAAmB,EAAE;IACxE,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,cAAc,CAAC,MAAM,EAAE,CAAC;QAC9B,cAAc,GAAG,IAAI,CAAC;IACxB,CAAC;AACH,CAAC,CAAC","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\n\nimport { getRaspExecutionStateChannelData, prepareRaspExecutionStateMapping } from '../../channels/raspExecutionState';\nimport { RaspExecutionState } from '../../models/raspExecutionState';\nimport type { RaspExecutionStateEventActions } from '../../types/types';\nimport { onInvalidCallback } from '../methods/native';\nimport { Talsec } from '../nativeModules';\n\nlet eventsListener: PluginListenerHandle | null = null;\nlet isInitializing = false;\n\nexport const registerRaspExecutionStateListener = async (config: RaspExecutionStateEventActions): Promise<void> => {\n if (isInitializing) {\n return;\n }\n isInitializing = true;\n\n if (eventsListener) {\n await eventsListener.remove();\n eventsListener = null;\n }\n\n const [channel, key] = await getRaspExecutionStateChannelData();\n await prepareRaspExecutionStateMapping();\n\n eventsListener = await Talsec.addListener(channel, async (event: any) => {\n if (event[key] == undefined) {\n onInvalidCallback();\n }\n switch (event[key]) {\n case RaspExecutionState.AllChecksFinished.value:\n config.allChecksFinished?.();\n break;\n default:\n onInvalidCallback();\n break;\n }\n });\n isInitializing = false;\n};\n\nexport const removeRaspExecutionStateListener = async (): Promise<void> => {\n if (eventsListener) {\n await eventsListener.remove();\n eventsListener = null;\n }\n};\n"]}
@@ -1,2 +1,3 @@
1
1
  import type { ThreatEventActions } from '../../types/types';
2
2
  export declare const registerThreatListener: (config: ThreatEventActions) => Promise<void>;
3
+ export declare const removeThreatListener: () => Promise<void>;
@@ -3,11 +3,21 @@ import { Threat } from '../../models/threat';
3
3
  import { parseMalwareData } from '../../utils/malware';
4
4
  import { onInvalidCallback } from '../methods/native';
5
5
  import { Talsec } from '../nativeModules';
6
+ let eventsListener = null;
7
+ let isInitializing = false;
6
8
  export const registerThreatListener = async (config) => {
9
+ if (isInitializing) {
10
+ return;
11
+ }
12
+ isInitializing = true;
13
+ if (eventsListener) {
14
+ await eventsListener.remove();
15
+ eventsListener = null;
16
+ }
7
17
  const [channel, key, malwareKey] = await getThreatChannelData();
8
18
  await prepareThreatMapping();
9
- await Talsec.addListener(channel, async (event) => {
10
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
19
+ eventsListener = await Talsec.addListener(channel, async (event) => {
20
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
11
21
  if (event[key] == undefined) {
12
22
  onInvalidCallback();
13
23
  }
@@ -75,10 +85,20 @@ export const registerThreatListener = async (config) => {
75
85
  case Threat.UnsecureWifi.value:
76
86
  (_w = config.unsecureWifi) === null || _w === void 0 ? void 0 : _w.call(config);
77
87
  break;
88
+ case Threat.Automation.value:
89
+ (_x = config.automation) === null || _x === void 0 ? void 0 : _x.call(config);
90
+ break;
78
91
  default:
79
92
  onInvalidCallback();
80
93
  break;
81
94
  }
82
95
  });
96
+ isInitializing = false;
97
+ };
98
+ export const removeThreatListener = async () => {
99
+ if (eventsListener) {
100
+ await eventsListener.remove();
101
+ eventsListener = null;
102
+ }
83
103
  };
84
104
  //# sourceMappingURL=threat.js.map