capacitor-freerasp 1.9.0 → 2.0.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 (53) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/README.md +3 -1
  3. package/android/build.gradle +5 -7
  4. package/android/src/main/java/com/aheaditec/freerasp/FreeraspPlugin.kt +70 -2
  5. package/android/src/main/java/com/aheaditec/freerasp/ScreenProtector.kt +162 -0
  6. package/android/src/main/java/com/aheaditec/freerasp/Threat.kt +5 -1
  7. package/android/src/main/java/com/aheaditec/freerasp/ThreatHandler.kt +9 -0
  8. package/dist/esm/definitions.d.ts +12 -0
  9. package/dist/esm/definitions.js +6 -0
  10. package/dist/esm/definitions.js.map +1 -1
  11. package/dist/esm/index.d.ts +5 -3
  12. package/dist/esm/index.js +22 -2
  13. package/dist/esm/index.js.map +1 -1
  14. package/dist/plugin.cjs.js +29 -1
  15. package/dist/plugin.cjs.js.map +1 -1
  16. package/dist/plugin.js +29 -1
  17. package/dist/plugin.js.map +1 -1
  18. package/ios/Plugin/FreeraspPlugin.swift +5 -1
  19. package/ios/Plugin/TalsecRuntime.xcframework/_CodeSignature/CodeDirectory +0 -0
  20. package/ios/Plugin/TalsecRuntime.xcframework/_CodeSignature/CodeRequirements-1 +0 -0
  21. package/ios/Plugin/TalsecRuntime.xcframework/_CodeSignature/CodeResources +87 -87
  22. package/ios/Plugin/TalsecRuntime.xcframework/_CodeSignature/CodeSignature +0 -0
  23. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/CurlWrapper.h +1 -1
  24. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/TalsecRuntime-Swift.h +1 -1
  25. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/curl.h +7 -7
  26. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/multi.h +4 -4
  27. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/options.h +1 -1
  28. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/urlapi.h +1 -1
  29. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Info.plist +0 -0
  30. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios.abi.json +316 -178
  31. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios.private.swiftinterface +2 -0
  32. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  33. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios.swiftinterface +2 -0
  34. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/TalsecRuntime +0 -0
  35. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/CurlWrapper.h +1 -1
  36. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/TalsecRuntime-Swift.h +2 -2
  37. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/curl.h +7 -7
  38. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/multi.h +4 -4
  39. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/options.h +1 -1
  40. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/urlapi.h +1 -1
  41. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Info.plist +0 -0
  42. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios-simulator.abi.json +316 -178
  43. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +2 -0
  44. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  45. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios-simulator.swiftinterface +2 -0
  46. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/x86_64-apple-ios-simulator.abi.json +316 -178
  47. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +2 -0
  48. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  49. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +2 -0
  50. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/TalsecRuntime +0 -0
  51. package/ios/Plugin/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/_CodeSignature/CodeResources +33 -33
  52. package/package.json +1 -1
  53. package/android/consumer-rules.pro +0 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,79 @@ 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.0.0] - 2024-03-25
9
+
10
+ - iOS SDK version: 6.9.0
11
+ - Android SDK version: 15.0.0
12
+
13
+ ### Capacitor
14
+
15
+ #### Changed
16
+
17
+ - Android SDK requires `kotlin_version` >= `2.0.0`
18
+
19
+ ### Android
20
+
21
+ #### Changed
22
+
23
+ - Compile API increased to 35, dependencies updated
24
+ - Internal library obfuscation reworked
25
+ - Root detection divided into 2 parts (quick initial checks, and time-demanding asynchronous post checks)
26
+
27
+ #### Fixed
28
+
29
+ - ANR issues bug-fixing
30
+
31
+ ### iOS
32
+
33
+ #### Added
34
+
35
+ - Improvement of the obfuscation of the SDK.
36
+
37
+ #### Changed
38
+
39
+ - Deep signing of the OpenSSL binaries.
40
+
41
+ ## [1.10.0] - 2025-03-05
42
+
43
+ - iOS SDK version: 6.8.0
44
+ - Android SDK version: 14.0.1
45
+
46
+ ### Capacitor
47
+
48
+ #### Added
49
+
50
+ - `blockScreenCapture` method to block/unblock screen capture
51
+ - `isScreenCaptureBlocked` method to get the current screen capture blocking status
52
+ - New callbacks:
53
+ - `screenshot`: Detects when a screenshot is taken
54
+ - `screenRecording`: Detects when screen recording is active
55
+
56
+ #### Changed
57
+
58
+ - Raised Android compileSDK level to 35
59
+ - Set minifyEnabled in plugin to `true` implicitly on Android
60
+
61
+ ### Android
62
+
63
+ #### Added
64
+
65
+ - Passive and active screenshot/screen recording protection
66
+
67
+ #### Changed
68
+
69
+ - Improved root detection
70
+
71
+ #### Fixed
72
+
73
+ - Proguard rules to address warnings from okhttp dependency
74
+
75
+ ### iOS
76
+
77
+ #### Added
78
+
79
+ - Passive Screenshot/Screen Recording detection
80
+
8
81
  ## [1.9.0] - 2024-12-29
9
82
 
10
83
  - iOS SDK version: 6.6.3
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  freeRASP for Capacitor is a mobile in-app protection and security monitoring plugin. It aims to cover the main aspects of RASP (Runtime App Self Protection) and application shielding.
10
10
 
11
- :loudspeaker: The official documentation has been moved to a new location. You can now find it [here](https://docs.talsec.app/docs-and-articles-portal). :loudspeaker:
11
+ :loudspeaker: [The official documentation has been moved to a new location. You can now find it here](https://docs.talsec.app/docs-and-articles-portal). :loudspeaker:
12
12
 
13
13
  # Overview
14
14
 
@@ -54,6 +54,8 @@ After the integration of freeRASP, make sure you visit the [freeMalwareDetection
54
54
 
55
55
  Visit the [GitBook page](https://docs.talsec.app/freerasp) for comprehensive and up-to-date guides, tutorials, and technical documentation specifically for freeRASP. It serves as your go-to resource, offering everything from basic instructions to advanced tips and tricks to help you get the most out of the project.
56
56
 
57
+ :loudspeaker: [The official documentation has been moved to a new location. You can now find it here](https://docs.talsec.app/docs-and-articles-portal). :loudspeaker:
58
+
57
59
  ## :link: Integration Guide
58
60
 
59
61
  For integrating freeRASP on the Capacitor platform, be sure to follow all the steps in the [Integration Guide](https://docs.talsec.app/freerasp/integration). This guide provides detailed instructions to help you achieve a smooth and efficient integration.
@@ -8,7 +8,7 @@ ext {
8
8
 
9
9
  buildscript {
10
10
  ext {
11
- kotlin_version = '1.8.22'
11
+ kotlin_version = '2.1.0'
12
12
  }
13
13
  repositories {
14
14
  google()
@@ -27,19 +27,17 @@ apply plugin: 'kotlinx-serialization'
27
27
 
28
28
  android {
29
29
  namespace "com.aheaditec.freerasp"
30
- compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 33
30
+ compileSdk 35
31
31
  defaultConfig {
32
32
  minSdkVersion 23
33
- targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 33
33
+ targetSdkVersion 35
34
34
  versionCode 1
35
35
  versionName "1.0"
36
36
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
37
- // now, the rule skips all classes of Capacitor plugin for freeRASP
38
- consumerProguardFiles 'consumer-rules.pro'
39
37
  }
40
38
  buildTypes {
41
39
  release {
42
- minifyEnabled false
40
+ minifyEnabled true
43
41
  proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
44
42
  }
45
43
  }
@@ -78,5 +76,5 @@ dependencies {
78
76
  androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
79
77
  androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
80
78
 
81
- implementation 'com.aheaditec.talsec.security:TalsecSecurity-Community-Capacitor:13.2.0'
79
+ implementation 'com.aheaditec.talsec.security:TalsecSecurity-Community-Capacitor:15.0.0'
82
80
  }
@@ -1,5 +1,6 @@
1
1
  package com.aheaditec.freerasp
2
2
 
3
+ import android.os.Build
3
4
  import android.os.Handler
4
5
  import android.os.HandlerThread
5
6
  import android.os.Looper
@@ -17,7 +18,6 @@ import com.getcapacitor.PluginCall
17
18
  import com.getcapacitor.PluginMethod
18
19
  import com.getcapacitor.annotation.CapacitorPlugin
19
20
  import org.json.JSONArray
20
- import java.lang.Exception
21
21
 
22
22
  @CapacitorPlugin(name = "Freerasp")
23
23
  class FreeraspPlugin : Plugin() {
@@ -38,8 +38,16 @@ class FreeraspPlugin : Plugin() {
38
38
  listener.registerListener(context)
39
39
  bridge.activity.runOnUiThread {
40
40
  Talsec.start(context, talsecConfig)
41
+ mainHandler.post {
42
+ talsecStarted = true
43
+ // This code must be called only AFTER Talsec.start
44
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
45
+ ScreenProtector.register(activity)
46
+ }
47
+ call.resolve(JSObject().put("started", true))
48
+ }
41
49
  }
42
- call.resolve(JSObject().put("started", true))
50
+
43
51
  } catch (e: Exception) {
44
52
  call.reject(
45
53
  "Error during Talsec Native plugin initialization - ${e.message}",
@@ -49,6 +57,13 @@ class FreeraspPlugin : Plugin() {
49
57
  }
50
58
  }
51
59
 
60
+ override fun handleOnStart() {
61
+ super.handleOnStart()
62
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
63
+ ScreenProtector.register(activity)
64
+ }
65
+ }
66
+
52
67
  override fun handleOnPause() {
53
68
  super.handleOnPause()
54
69
  if (activity.isFinishing) {
@@ -65,6 +80,13 @@ class FreeraspPlugin : Plugin() {
65
80
  }
66
81
  }
67
82
 
83
+ override fun handleOnStop() {
84
+ super.handleOnStop()
85
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
86
+ ScreenProtector.unregister(activity)
87
+ }
88
+ }
89
+
68
90
  override fun handleOnDestroy() {
69
91
  super.handleOnDestroy()
70
92
  backgroundHandlerThread.quitSafely()
@@ -142,6 +164,49 @@ class FreeraspPlugin : Plugin() {
142
164
  }
143
165
  }
144
166
 
167
+ /**
168
+ * Method to set screen capture state
169
+ * @param enable Pass `true` to block screen capture, `false` to enable it
170
+ */
171
+ @PluginMethod
172
+ fun blockScreenCapture(call: PluginCall) {
173
+ val enable = call.getBoolean("enable") ?: run {
174
+ call.reject(
175
+ "Enable argument is missing or not a boolean.", "MissingArgumentError"
176
+ )
177
+ return
178
+ }
179
+
180
+ activity?.runOnUiThread {
181
+ try {
182
+ Talsec.blockScreenCapture(context, enable)
183
+ call.resolve(JSObject().put("result", true))
184
+ } catch (e: Exception) {
185
+ call.reject(
186
+ "Error while setting screen capture: ${e.message}", "BlockScreenCaptureError"
187
+ )
188
+ }
189
+ } ?: run {
190
+ call.reject("Cannot block screen capture, activity is null.", "BlockScreenCaptureError")
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Method to check if screen capturing is currently blocked
196
+ */
197
+ @PluginMethod
198
+ fun isScreenCaptureBlocked(call: PluginCall) {
199
+ try {
200
+ val isBlocked = Talsec.isScreenCaptureBlocked()
201
+ call.resolve(JSObject().put("result", isBlocked))
202
+ } catch (e: Exception) {
203
+ call.reject(
204
+ "Error while checking if screen capture is blocked: ${e.message}",
205
+ "IsScreenCaptureBlockedError"
206
+ )
207
+ }
208
+ }
209
+
145
210
  internal fun notifyListeners(threat: Threat) {
146
211
  notifyListeners(THREAT_CHANNEL_NAME, JSObject().put(THREAT_CHANNEL_KEY, threat.value), true)
147
212
  }
@@ -179,6 +244,7 @@ class FreeraspPlugin : Plugin() {
179
244
  return talsecBuilder.build()
180
245
  }
181
246
 
247
+
182
248
  companion object {
183
249
  private val THREAT_CHANNEL_NAME = (10000..999999999).random()
184
250
  .toString() // name of the channel over which threat callbacks are sent
@@ -189,5 +255,7 @@ class FreeraspPlugin : Plugin() {
189
255
  private val backgroundHandlerThread = HandlerThread("BackgroundThread").apply { start() }
190
256
  private val backgroundHandler = Handler(backgroundHandlerThread.looper)
191
257
  private val mainHandler = Handler(Looper.getMainLooper())
258
+
259
+ internal var talsecStarted = false
192
260
  }
193
261
  }
@@ -0,0 +1,162 @@
1
+ package com.aheaditec.freerasp
2
+
3
+ import android.annotation.SuppressLint
4
+ import android.app.Activity
5
+ import android.app.Activity.ScreenCaptureCallback
6
+ import android.content.Context
7
+ import android.content.pm.PackageManager
8
+ import android.os.Build
9
+ import android.util.Log
10
+ import android.view.WindowManager.SCREEN_RECORDING_STATE_VISIBLE
11
+ import androidx.annotation.RequiresApi
12
+ import androidx.core.content.ContextCompat
13
+ import com.aheaditec.talsec_security.security.api.Talsec
14
+ import java.util.function.Consumer
15
+
16
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
17
+ internal object ScreenProtector {
18
+ private const val TAG = "TalsecScreenProtector"
19
+ private const val SCREEN_CAPTURE_PERMISSION = "android.permission.DETECT_SCREEN_CAPTURE"
20
+ private const val SCREEN_RECORDING_PERMISSION = "android.permission.DETECT_SCREEN_RECORDING"
21
+ private var registered = false
22
+ private val screenCaptureCallback = ScreenCaptureCallback { Talsec.onScreenshotDetected() }
23
+ private val screenRecordCallback: Consumer<Int> = Consumer<Int> { state ->
24
+ if (state == SCREEN_RECORDING_STATE_VISIBLE) {
25
+ Talsec.onScreenRecordingDetected()
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Registers screenshot and screen recording detector with the given activity
31
+ *
32
+ * **IMPORTANT**: android.permission.DETECT_SCREEN_CAPTURE and
33
+ * android.permission.DETECT_SCREEN_RECORDING must be
34
+ * granted for the app in the AndroidManifest.xml
35
+ */
36
+ internal fun register(activity: Activity) {
37
+ if (!FreeraspPlugin.talsecStarted || registered) {
38
+ return
39
+ }
40
+
41
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
42
+ registerScreenCapture(activity)
43
+ }
44
+
45
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
46
+ registerScreenRecording(activity)
47
+ }
48
+ registered = true
49
+ }
50
+
51
+ /**
52
+ * Register Talsec Screen Capture (screenshot) Detector for given activity instance.
53
+ * The MainActivity of the app is registered by the plugin itself, other
54
+ * activities bust be registered manually as described in the integration guide.
55
+ *
56
+ * Missing permission is suppressed because the decision to use the screen
57
+ * capture API is made by developer, and not enforced by the library.
58
+ *
59
+ * **IMPORTANT**: android.permission.DETECT_SCREEN_CAPTURE (API 34+) must be
60
+ * granted for the app in the AndroidManifest.xml
61
+ */
62
+ @SuppressLint("MissingPermission")
63
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
64
+ private fun registerScreenCapture(activity: Activity) {
65
+ val context = activity.applicationContext
66
+ if (!hasPermission(context, SCREEN_CAPTURE_PERMISSION)) {
67
+ reportMissingPermission("screenshot", SCREEN_CAPTURE_PERMISSION)
68
+ return
69
+ }
70
+
71
+ activity.registerScreenCaptureCallback(context.mainExecutor, screenCaptureCallback)
72
+ }
73
+
74
+ /**
75
+ * Register Talsec Screen Recording Detector for given activity instance.
76
+ * The MainActivity of the app is registered by the plugin itself, other
77
+ * activities bust be registered manually as described in the integration guide.
78
+ *
79
+ * Missing permission is suppressed because the decision to use the screen
80
+ * capture API is made by developer, and not enforced by the library.
81
+ *
82
+ * **IMPORTANT**: android.permission.DETECT_SCREEN_RECORDING (API 35+) must be
83
+ * granted for the app in the AndroidManifest.xml
84
+ */
85
+ @SuppressLint("MissingPermission")
86
+ @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
87
+ private fun registerScreenRecording(activity: Activity) {
88
+ val context = activity.applicationContext
89
+ if (!hasPermission(context, SCREEN_RECORDING_PERMISSION)) {
90
+ reportMissingPermission("screen record", SCREEN_RECORDING_PERMISSION)
91
+ return
92
+ }
93
+
94
+ val initialState = activity.windowManager.addScreenRecordingCallback(
95
+ context.mainExecutor, screenRecordCallback
96
+ )
97
+ screenRecordCallback.accept(initialState)
98
+
99
+ }
100
+
101
+ /**
102
+ * Unregisters screenshot and screen recording detector with the given activity
103
+ *
104
+ * **IMPORTANT**: android.permission.DETECT_SCREEN_CAPTURE and
105
+ * android.permission.DETECT_SCREEN_RECORDING must be
106
+ * granted for the app in the AndroidManifest.xml
107
+ */
108
+ @SuppressLint("MissingPermission")
109
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
110
+ internal fun unregister(activity: Activity) {
111
+ if (!FreeraspPlugin.talsecStarted || !registered) {
112
+ return
113
+ }
114
+
115
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
116
+ unregisterScreenCapture(activity)
117
+ }
118
+
119
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
120
+ unregisterScreenRecording(activity)
121
+ }
122
+ registered = false
123
+ }
124
+
125
+ // Missing permission is suppressed because the decision to use the screen capture API is made
126
+ // by developer, and not enforced by the library.
127
+ @SuppressLint("MissingPermission")
128
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
129
+ private fun unregisterScreenCapture(activity: Activity) {
130
+ val context = activity.applicationContext
131
+ if (!hasPermission(context, SCREEN_CAPTURE_PERMISSION)) {
132
+ return
133
+ }
134
+ activity.unregisterScreenCaptureCallback(screenCaptureCallback)
135
+ }
136
+
137
+ // Missing permission is suppressed because the decision to use the screen capture API is made
138
+ // by developer, and not enforced by the library.
139
+ @SuppressLint("MissingPermission")
140
+ @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
141
+ private fun unregisterScreenRecording(activity: Activity) {
142
+ val context = activity.applicationContext
143
+ if (!hasPermission(context, SCREEN_RECORDING_PERMISSION)) {
144
+ return
145
+ }
146
+
147
+ activity.windowManager?.removeScreenRecordingCallback(screenRecordCallback)
148
+ }
149
+
150
+ private fun hasPermission(context: Context, permission: String): Boolean {
151
+ return ContextCompat.checkSelfPermission(
152
+ context, permission
153
+ ) == PackageManager.PERMISSION_GRANTED
154
+ }
155
+
156
+ private fun reportMissingPermission(protectionType: String, permission: String) {
157
+ Log.e(
158
+ TAG,
159
+ "Failed to register $protectionType callback. Check if $permission permission is granted in AndroidManifest.xml"
160
+ )
161
+ }
162
+ }
@@ -25,6 +25,8 @@ internal sealed class Threat(val value: Int) {
25
25
  object DevMode : Threat((10000..999999999).random())
26
26
  object Malware : Threat((10000..999999999).random())
27
27
  object ADBEnabled : Threat((10000..999999999).random())
28
+ object Screenshot : Threat((10000..999999999).random())
29
+ object ScreenRecording : Threat((10000..999999999).random())
28
30
 
29
31
  companion object {
30
32
  internal fun getThreatValues(): JSONArray {
@@ -44,7 +46,9 @@ internal sealed class Threat(val value: Int) {
44
46
  ObfuscationIssues.value,
45
47
  DevMode.value,
46
48
  Malware.value,
47
- ADBEnabled.value
49
+ ADBEnabled.value,
50
+ Screenshot.value,
51
+ ScreenRecording.value
48
52
  ))
49
53
  )
50
54
  }
@@ -61,4 +61,13 @@ internal class TalsecThreatHandler(private val instance: FreeraspPlugin) :
61
61
  override fun onSystemVPNDetected() {
62
62
  instance.notifyListeners(Threat.SystemVPN)
63
63
  }
64
+
65
+ override fun onScreenshotDetected() {
66
+ instance.notifyListeners(Threat.Screenshot)
67
+ }
68
+
69
+ override fun onScreenRecordingDetected() {
70
+ instance.notifyListeners(Threat.ScreenRecording)
71
+ }
72
+
64
73
  }
@@ -22,6 +22,14 @@ export interface FreeraspPlugin {
22
22
  }): Promise<{
23
23
  result: string;
24
24
  }>;
25
+ blockScreenCapture(options: {
26
+ enable: boolean;
27
+ }): Promise<{
28
+ result: boolean;
29
+ }>;
30
+ isScreenCaptureBlocked(): Promise<{
31
+ result: boolean;
32
+ }>;
25
33
  }
26
34
  export declare type FreeraspConfig = {
27
35
  androidConfig?: AndroidConfig;
@@ -72,6 +80,8 @@ export declare type NativeEventEmitterActions = {
72
80
  systemVPN?: () => any;
73
81
  malware?: (suspiciousApps: SuspiciousAppInfo[]) => any;
74
82
  adbEnabled?: () => any;
83
+ screenshot?: () => any;
84
+ screenRecording?: () => any;
75
85
  };
76
86
  export declare class Threat {
77
87
  value: number;
@@ -91,6 +101,8 @@ export declare class Threat {
91
101
  static DevMode: Threat;
92
102
  static Malware: Threat;
93
103
  static ADBEnabled: Threat;
104
+ static Screenshot: Threat;
105
+ static ScreenRecording: Threat;
94
106
  constructor(value: number);
95
107
  static getValues(): Threat[];
96
108
  }
@@ -21,6 +21,8 @@ export class Threat {
21
21
  this.DevMode,
22
22
  this.Malware,
23
23
  this.ADBEnabled,
24
+ this.Screenshot,
25
+ this.ScreenRecording,
24
26
  ]
25
27
  : [
26
28
  this.AppIntegrity,
@@ -34,6 +36,8 @@ export class Threat {
34
36
  this.DeviceBinding,
35
37
  this.DeviceID,
36
38
  this.UnofficialStore,
39
+ this.Screenshot,
40
+ this.ScreenRecording,
37
41
  ];
38
42
  }
39
43
  }
@@ -53,4 +57,6 @@ Threat.ObfuscationIssues = new Threat(0);
53
57
  Threat.DevMode = new Threat(0);
54
58
  Threat.Malware = new Threat(0);
55
59
  Threat.ADBEnabled = new Threat(0);
60
+ Threat.Screenshot = new Threat(0);
61
+ Threat.ScreenRecording = new Threat(0);
56
62
  //# sourceMappingURL=definitions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAyE5C,MAAM,OAAO,MAAM;IAoBjB,YAAY,KAAa;QACvB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,MAAM,CAAC,SAAS;QACd,OAAO,SAAS,CAAC,WAAW,EAAE,KAAK,SAAS;YAC1C,CAAC,CAAC;gBACE,IAAI,CAAC,YAAY;gBACjB,IAAI,CAAC,gBAAgB;gBACrB,IAAI,CAAC,KAAK;gBACV,IAAI,CAAC,KAAK;gBACV,IAAI,CAAC,QAAQ;gBACb,IAAI,CAAC,SAAS;gBACd,IAAI,CAAC,0BAA0B;gBAC/B,IAAI,CAAC,SAAS;gBACd,IAAI,CAAC,aAAa;gBAClB,IAAI,CAAC,eAAe;gBACpB,IAAI,CAAC,OAAO;gBACZ,IAAI,CAAC,iBAAiB;gBACtB,IAAI,CAAC,OAAO;gBACZ,IAAI,CAAC,OAAO;gBACZ,IAAI,CAAC,UAAU;aAChB;YACH,CAAC,CAAC;gBACE,IAAI,CAAC,YAAY;gBACjB,IAAI,CAAC,gBAAgB;gBACrB,IAAI,CAAC,KAAK;gBACV,IAAI,CAAC,KAAK;gBACV,IAAI,CAAC,QAAQ;gBACb,IAAI,CAAC,SAAS;gBACd,IAAI,CAAC,0BAA0B;gBAC/B,IAAI,CAAC,SAAS;gBACd,IAAI,CAAC,aAAa;gBAClB,IAAI,CAAC,QAAQ;gBACb,IAAI,CAAC,eAAe;aACrB,CAAC;IACR,CAAC;;AArDM,mBAAY,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AAC7B,uBAAgB,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AACjC,YAAK,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AACtB,YAAK,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AACtB,eAAQ,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AACzB,gBAAS,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AAC1B,iCAA0B,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AAC3C,gBAAS,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AAC1B,oBAAa,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AAC9B,eAAQ,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AACzB,sBAAe,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AAChC,cAAO,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AACxB,wBAAiB,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AAClC,cAAO,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AACxB,cAAO,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AACxB,iBAAU,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC","sourcesContent":["import { Capacitor } from '@capacitor/core';\n\nexport interface FreeraspPlugin {\n addListener(listener: string, callback: (event: any) => void): any;\n talsecStart(options: {\n config: FreeraspConfig;\n }): Promise<{ started: boolean }>;\n onInvalidCallback(): void;\n getThreatIdentifiers(): Promise<{ ids: number[] }>;\n getThreatChannelData(): Promise<{ ids: [string, string, string] }>;\n addToWhitelist(options: {\n packageName: string;\n }): Promise<{ result: boolean }>;\n getAppIcon(options: { packageName: string }): Promise<{ result: string }>;\n}\n\nexport type FreeraspConfig = {\n androidConfig?: AndroidConfig;\n iosConfig?: IOSConfig;\n watcherMail: string;\n isProd?: boolean;\n};\n\nexport type AndroidConfig = {\n packageName: string;\n certificateHashes: string[];\n supportedAlternativeStores?: string[];\n malwareConfig?: MalwareConfig;\n};\n\nexport type IOSConfig = {\n appBundleId: string;\n appTeamId: string;\n};\n\nexport type MalwareConfig = {\n blacklistedHashes?: string[];\n blacklistedPackageNames?: string[];\n suspiciousPermissions?: string[][];\n whitelistedInstallationSources?: string[];\n};\n\nexport type SuspiciousAppInfo = {\n packageInfo: PackageInfo;\n reason: string;\n};\n\nexport type PackageInfo = {\n packageName: string;\n appName?: string;\n version?: string;\n appIcon?: string;\n installerStore?: string;\n};\n\nexport type NativeEventEmitterActions = {\n privilegedAccess?: () => any;\n debug?: () => any;\n simulator?: () => any;\n appIntegrity?: () => any;\n unofficialStore?: () => any;\n hooks?: () => any;\n deviceBinding?: () => any;\n deviceID?: () => any;\n passcode?: () => any;\n secureHardwareNotAvailable?: () => any;\n obfuscationIssues?: () => any;\n devMode?: () => any;\n systemVPN?: () => any;\n malware?: (suspiciousApps: SuspiciousAppInfo[]) => any;\n adbEnabled?: () => any;\n};\n\nexport class Threat {\n value: number;\n\n static AppIntegrity = new Threat(0);\n static PrivilegedAccess = new Threat(0);\n static Debug = new Threat(0);\n static Hooks = new Threat(0);\n static Passcode = new Threat(0);\n static Simulator = new Threat(0);\n static SecureHardwareNotAvailable = new Threat(0);\n static SystemVPN = new Threat(0);\n static DeviceBinding = new Threat(0);\n static DeviceID = new Threat(0);\n static UnofficialStore = new Threat(0);\n static Overlay = new Threat(0);\n static ObfuscationIssues = new Threat(0);\n static DevMode = new Threat(0);\n static Malware = new Threat(0);\n static ADBEnabled = new Threat(0);\n\n constructor(value: number) {\n this.value = value;\n }\n\n static getValues(): Threat[] {\n return Capacitor.getPlatform() === 'android'\n ? [\n this.AppIntegrity,\n this.PrivilegedAccess,\n this.Debug,\n this.Hooks,\n this.Passcode,\n this.Simulator,\n this.SecureHardwareNotAvailable,\n this.SystemVPN,\n this.DeviceBinding,\n this.UnofficialStore,\n this.Overlay,\n this.ObfuscationIssues,\n this.DevMode,\n this.Malware,\n this.ADBEnabled,\n ]\n : [\n this.AppIntegrity,\n this.PrivilegedAccess,\n this.Debug,\n this.Hooks,\n this.Passcode,\n this.Simulator,\n this.SecureHardwareNotAvailable,\n this.SystemVPN,\n this.DeviceBinding,\n this.DeviceID,\n this.UnofficialStore,\n ];\n }\n}\n"]}
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AA+E5C,MAAM,OAAO,MAAM;IAsBjB,YAAY,KAAa;QACvB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,MAAM,CAAC,SAAS;QACd,OAAO,SAAS,CAAC,WAAW,EAAE,KAAK,SAAS;YAC1C,CAAC,CAAC;gBACE,IAAI,CAAC,YAAY;gBACjB,IAAI,CAAC,gBAAgB;gBACrB,IAAI,CAAC,KAAK;gBACV,IAAI,CAAC,KAAK;gBACV,IAAI,CAAC,QAAQ;gBACb,IAAI,CAAC,SAAS;gBACd,IAAI,CAAC,0BAA0B;gBAC/B,IAAI,CAAC,SAAS;gBACd,IAAI,CAAC,aAAa;gBAClB,IAAI,CAAC,eAAe;gBACpB,IAAI,CAAC,OAAO;gBACZ,IAAI,CAAC,iBAAiB;gBACtB,IAAI,CAAC,OAAO;gBACZ,IAAI,CAAC,OAAO;gBACZ,IAAI,CAAC,UAAU;gBACf,IAAI,CAAC,UAAU;gBACf,IAAI,CAAC,eAAe;aACrB;YACH,CAAC,CAAC;gBACE,IAAI,CAAC,YAAY;gBACjB,IAAI,CAAC,gBAAgB;gBACrB,IAAI,CAAC,KAAK;gBACV,IAAI,CAAC,KAAK;gBACV,IAAI,CAAC,QAAQ;gBACb,IAAI,CAAC,SAAS;gBACd,IAAI,CAAC,0BAA0B;gBAC/B,IAAI,CAAC,SAAS;gBACd,IAAI,CAAC,aAAa;gBAClB,IAAI,CAAC,QAAQ;gBACb,IAAI,CAAC,eAAe;gBACpB,IAAI,CAAC,UAAU;gBACf,IAAI,CAAC,eAAe;aACrB,CAAC;IACR,CAAC;;AA3DM,mBAAY,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AAC7B,uBAAgB,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AACjC,YAAK,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AACtB,YAAK,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AACtB,eAAQ,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AACzB,gBAAS,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AAC1B,iCAA0B,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AAC3C,gBAAS,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AAC1B,oBAAa,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AAC9B,eAAQ,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AACzB,sBAAe,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AAChC,cAAO,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AACxB,wBAAiB,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AAClC,cAAO,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AACxB,cAAO,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AACxB,iBAAU,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AAC3B,iBAAU,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AAC3B,sBAAe,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC","sourcesContent":["import { Capacitor } from '@capacitor/core';\n\nexport interface FreeraspPlugin {\n addListener(listener: string, callback: (event: any) => void): any;\n talsecStart(options: {\n config: FreeraspConfig;\n }): Promise<{ started: boolean }>;\n onInvalidCallback(): void;\n getThreatIdentifiers(): Promise<{ ids: number[] }>;\n getThreatChannelData(): Promise<{ ids: [string, string, string] }>;\n addToWhitelist(options: {\n packageName: string;\n }): Promise<{ result: boolean }>;\n getAppIcon(options: { packageName: string }): Promise<{ result: string }>;\n blockScreenCapture(options: {\n enable: boolean;\n }): Promise<{ result: boolean }>;\n isScreenCaptureBlocked(): Promise<{ result: boolean }>;\n}\n\nexport type FreeraspConfig = {\n androidConfig?: AndroidConfig;\n iosConfig?: IOSConfig;\n watcherMail: string;\n isProd?: boolean;\n};\n\nexport type AndroidConfig = {\n packageName: string;\n certificateHashes: string[];\n supportedAlternativeStores?: string[];\n malwareConfig?: MalwareConfig;\n};\n\nexport type IOSConfig = {\n appBundleId: string;\n appTeamId: string;\n};\n\nexport type MalwareConfig = {\n blacklistedHashes?: string[];\n blacklistedPackageNames?: string[];\n suspiciousPermissions?: string[][];\n whitelistedInstallationSources?: string[];\n};\n\nexport type SuspiciousAppInfo = {\n packageInfo: PackageInfo;\n reason: string;\n};\n\nexport type PackageInfo = {\n packageName: string;\n appName?: string;\n version?: string;\n appIcon?: string;\n installerStore?: string;\n};\n\nexport type NativeEventEmitterActions = {\n privilegedAccess?: () => any;\n debug?: () => any;\n simulator?: () => any;\n appIntegrity?: () => any;\n unofficialStore?: () => any;\n hooks?: () => any;\n deviceBinding?: () => any;\n deviceID?: () => any;\n passcode?: () => any;\n secureHardwareNotAvailable?: () => any;\n obfuscationIssues?: () => any;\n devMode?: () => any;\n systemVPN?: () => any;\n malware?: (suspiciousApps: SuspiciousAppInfo[]) => any;\n adbEnabled?: () => any;\n screenshot?: () => any;\n screenRecording?: () => any;\n};\n\nexport class Threat {\n value: number;\n\n static AppIntegrity = new Threat(0);\n static PrivilegedAccess = new Threat(0);\n static Debug = new Threat(0);\n static Hooks = new Threat(0);\n static Passcode = new Threat(0);\n static Simulator = new Threat(0);\n static SecureHardwareNotAvailable = new Threat(0);\n static SystemVPN = new Threat(0);\n static DeviceBinding = new Threat(0);\n static DeviceID = new Threat(0);\n static UnofficialStore = new Threat(0);\n static Overlay = new Threat(0);\n static ObfuscationIssues = new Threat(0);\n static DevMode = new Threat(0);\n static Malware = new Threat(0);\n static ADBEnabled = new Threat(0);\n static Screenshot = new Threat(0);\n static ScreenRecording = new Threat(0);\n\n constructor(value: number) {\n this.value = value;\n }\n\n static getValues(): Threat[] {\n return Capacitor.getPlatform() === 'android'\n ? [\n this.AppIntegrity,\n this.PrivilegedAccess,\n this.Debug,\n this.Hooks,\n this.Passcode,\n this.Simulator,\n this.SecureHardwareNotAvailable,\n this.SystemVPN,\n this.DeviceBinding,\n this.UnofficialStore,\n this.Overlay,\n this.ObfuscationIssues,\n this.DevMode,\n this.Malware,\n this.ADBEnabled,\n this.Screenshot,\n this.ScreenRecording,\n ]\n : [\n this.AppIntegrity,\n this.PrivilegedAccess,\n this.Debug,\n this.Hooks,\n this.Passcode,\n this.Simulator,\n this.SecureHardwareNotAvailable,\n this.SystemVPN,\n this.DeviceBinding,\n this.DeviceID,\n this.UnofficialStore,\n this.Screenshot,\n this.ScreenRecording,\n ];\n }\n}\n"]}
@@ -1,9 +1,11 @@
1
1
  import type { FreeraspPlugin, FreeraspConfig, NativeEventEmitterActions } from './definitions';
2
2
  declare const Freerasp: FreeraspPlugin;
3
- declare const setThreatListeners: <T extends NativeEventEmitterActions>(callbacks: T & Record<Exclude<keyof T, "privilegedAccess" | "debug" | "simulator" | "appIntegrity" | "unofficialStore" | "hooks" | "deviceBinding" | "deviceID" | "passcode" | "secureHardwareNotAvailable" | "obfuscationIssues" | "devMode" | "systemVPN" | "malware" | "adbEnabled">, []>) => Promise<void>;
3
+ declare const setThreatListeners: <T extends NativeEventEmitterActions>(callbacks: T & Record<Exclude<keyof T, "privilegedAccess" | "debug" | "simulator" | "appIntegrity" | "unofficialStore" | "hooks" | "deviceBinding" | "deviceID" | "passcode" | "secureHardwareNotAvailable" | "obfuscationIssues" | "devMode" | "systemVPN" | "malware" | "adbEnabled" | "screenshot" | "screenRecording">, []>) => Promise<void>;
4
4
  declare const removeThreatListeners: () => void;
5
- declare const startFreeRASP: <T extends NativeEventEmitterActions>(config: FreeraspConfig, reactions: T & Record<Exclude<keyof T, "privilegedAccess" | "debug" | "simulator" | "appIntegrity" | "unofficialStore" | "hooks" | "deviceBinding" | "deviceID" | "passcode" | "secureHardwareNotAvailable" | "obfuscationIssues" | "devMode" | "systemVPN" | "malware" | "adbEnabled">, []>) => Promise<boolean>;
5
+ declare const startFreeRASP: <T extends NativeEventEmitterActions>(config: FreeraspConfig, reactions: T & Record<Exclude<keyof T, "privilegedAccess" | "debug" | "simulator" | "appIntegrity" | "unofficialStore" | "hooks" | "deviceBinding" | "deviceID" | "passcode" | "secureHardwareNotAvailable" | "obfuscationIssues" | "devMode" | "systemVPN" | "malware" | "adbEnabled" | "screenshot" | "screenRecording">, []>) => Promise<boolean>;
6
6
  declare const addToWhitelist: (packageName: string) => Promise<boolean>;
7
7
  declare const getAppIcon: (packageName: string) => Promise<string>;
8
+ declare const blockScreenCapture: (enable: boolean) => Promise<boolean>;
9
+ declare const isScreenCaptureBlocked: () => Promise<boolean>;
8
10
  export * from './definitions';
9
- export { Freerasp, startFreeRASP, setThreatListeners, removeThreatListeners, addToWhitelist, getAppIcon, };
11
+ export { Freerasp, startFreeRASP, setThreatListeners, removeThreatListeners, addToWhitelist, getAppIcon, blockScreenCapture, isScreenCaptureBlocked, };
package/dist/esm/index.js CHANGED
@@ -49,7 +49,7 @@ const setThreatListeners = async (callbacks) => {
49
49
  const [channel, key, malwareKey] = await getThreatChannelData();
50
50
  await prepareMapping();
51
51
  await Freerasp.addListener(channel, async (event) => {
52
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
52
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
53
53
  if (event[key] === undefined) {
54
54
  onInvalidCallback();
55
55
  }
@@ -99,6 +99,12 @@ const setThreatListeners = async (callbacks) => {
99
99
  case Threat.ADBEnabled.value:
100
100
  (_q = callbacks.adbEnabled) === null || _q === void 0 ? void 0 : _q.call(callbacks);
101
101
  break;
102
+ case Threat.Screenshot.value:
103
+ (_r = callbacks.screenshot) === null || _r === void 0 ? void 0 : _r.call(callbacks);
104
+ break;
105
+ case Threat.ScreenRecording.value:
106
+ (_s = callbacks.screenRecording) === null || _s === void 0 ? void 0 : _s.call(callbacks);
107
+ break;
102
108
  default:
103
109
  onInvalidCallback();
104
110
  break;
@@ -133,6 +139,20 @@ const getAppIcon = async (packageName) => {
133
139
  const { result } = await Freerasp.getAppIcon({ packageName });
134
140
  return result;
135
141
  };
142
+ const blockScreenCapture = async (enable) => {
143
+ if (Capacitor.getPlatform() === 'ios') {
144
+ return Promise.reject('Block Screen Capture is not available on iOS');
145
+ }
146
+ const { result } = await Freerasp.blockScreenCapture({ enable });
147
+ return result;
148
+ };
149
+ const isScreenCaptureBlocked = async () => {
150
+ if (Capacitor.getPlatform() === 'ios') {
151
+ return Promise.reject('Screen Capture Status is not available on iOS');
152
+ }
153
+ const { result } = await Freerasp.isScreenCaptureBlocked();
154
+ return result;
155
+ };
136
156
  export * from './definitions';
137
- export { Freerasp, startFreeRASP, setThreatListeners, removeThreatListeners, addToWhitelist, getAppIcon, };
157
+ export { Freerasp, startFreeRASP, setThreatListeners, removeThreatListeners, addToWhitelist, getAppIcon, blockScreenCapture, isScreenCaptureBlocked, };
138
158
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { Capacitor, registerPlugin } from '@capacitor/core';\n\nimport type {\n FreeraspPlugin,\n FreeraspConfig,\n NativeEventEmitterActions,\n SuspiciousAppInfo,\n PackageInfo,\n} from './definitions';\nimport { Threat } from './definitions';\nimport { getThreatCount, itemsHaveType } from './utils';\n\nconst activeListeners: any[] = [];\n\nconst Freerasp = registerPlugin<FreeraspPlugin>('Freerasp', {});\n\nconst onInvalidCallback = (): void => {\n Freerasp.onInvalidCallback();\n};\n\nconst getThreatIdentifiers = async (): Promise<number[]> => {\n const { ids } = await Freerasp.getThreatIdentifiers();\n if (ids.length !== getThreatCount() || !itemsHaveType(ids, 'number')) {\n onInvalidCallback();\n }\n return ids;\n};\n\nconst getThreatChannelData = async (): Promise<[string, string, string]> => {\n const dataLength = Capacitor.getPlatform() === 'ios' ? 2 : 3;\n const { ids } = await Freerasp.getThreatChannelData();\n if (ids.length !== dataLength || !itemsHaveType(ids, 'string')) {\n onInvalidCallback();\n }\n return ids;\n};\n\nconst prepareMapping = async (): Promise<void> => {\n const newValues = await getThreatIdentifiers();\n const threats = Threat.getValues();\n\n threats.map((threat, index) => {\n threat.value = newValues[index];\n });\n};\n\n// parses base64-encoded malware data to SuspiciousAppInfo[]\nconst parseMalwareData = async (\n data: string[],\n): Promise<SuspiciousAppInfo[]> => {\n return new Promise((resolve, reject) => {\n try {\n const suspiciousAppData = data.map(entry => toSuspiciousAppInfo(entry));\n resolve(suspiciousAppData);\n } catch (error: any) {\n reject(`Parsing app data failed: ${error}`);\n }\n });\n};\n\nconst toSuspiciousAppInfo = (base64Value: string): SuspiciousAppInfo => {\n const data = JSON.parse(atob(base64Value));\n const packageInfo = data.packageInfo as PackageInfo;\n return { packageInfo, reason: data.reason } as SuspiciousAppInfo;\n};\n\nconst setThreatListeners = async <T extends NativeEventEmitterActions>(\n callbacks: T & Record<Exclude<keyof T, keyof NativeEventEmitterActions>, []>,\n): Promise<void> => {\n const [channel, key, malwareKey] = await getThreatChannelData();\n await prepareMapping();\n\n await Freerasp.addListener(channel, async (event: any) => {\n if (event[key] === undefined) {\n onInvalidCallback();\n }\n switch (event[key]) {\n case Threat.PrivilegedAccess.value:\n callbacks.privilegedAccess?.();\n break;\n case Threat.Debug.value:\n callbacks.debug?.();\n break;\n case Threat.Simulator.value:\n callbacks.simulator?.();\n break;\n case Threat.AppIntegrity.value:\n callbacks.appIntegrity?.();\n break;\n case Threat.UnofficialStore.value:\n callbacks.unofficialStore?.();\n break;\n case Threat.Hooks.value:\n callbacks.hooks?.();\n break;\n case Threat.DeviceBinding.value:\n callbacks.deviceBinding?.();\n break;\n case Threat.Passcode.value:\n callbacks.passcode?.();\n break;\n case Threat.SecureHardwareNotAvailable.value:\n callbacks.secureHardwareNotAvailable?.();\n break;\n case Threat.ObfuscationIssues.value:\n callbacks.obfuscationIssues?.();\n break;\n case Threat.DeviceID.value:\n callbacks.deviceID?.();\n break;\n case Threat.DevMode.value:\n callbacks.devMode?.();\n break;\n case Threat.SystemVPN.value:\n callbacks.systemVPN?.();\n break;\n case Threat.Malware.value:\n callbacks.malware?.(await parseMalwareData(event[malwareKey]));\n break;\n case Threat.ADBEnabled.value:\n callbacks.adbEnabled?.();\n break;\n default:\n onInvalidCallback();\n break;\n }\n });\n};\n\nconst removeThreatListeners = (): void => {\n activeListeners.forEach(listener => listener.remove());\n};\n\nconst startFreeRASP = async <T extends NativeEventEmitterActions>(\n config: FreeraspConfig,\n reactions: T & Record<Exclude<keyof T, keyof NativeEventEmitterActions>, []>,\n): Promise<boolean> => {\n await setThreatListeners(reactions);\n try {\n const { started } = await Freerasp.talsecStart({ config });\n return started;\n } catch (e: any) {\n console.error(`${e.code}: ${e.message}`);\n return Promise.reject(`${e.code}: ${e.message}`);\n }\n};\n\nconst addToWhitelist = async (packageName: string): Promise<boolean> => {\n if (Capacitor.getPlatform() === 'ios') {\n return Promise.reject('Malware detection not available on iOS');\n }\n const { result } = await Freerasp.addToWhitelist({ packageName });\n return result;\n};\n\nconst getAppIcon = async (packageName: string): Promise<string> => {\n if (Capacitor.getPlatform() === 'ios') {\n return Promise.reject(\n 'App icon retrieval for Malware detection not available on iOS',\n );\n }\n const { result } = await Freerasp.getAppIcon({ packageName });\n return result;\n};\n\nexport * from './definitions';\nexport {\n Freerasp,\n startFreeRASP,\n setThreatListeners,\n removeThreatListeners,\n addToWhitelist,\n getAppIcon,\n};\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { Capacitor, registerPlugin } from '@capacitor/core';\n\nimport type {\n FreeraspPlugin,\n FreeraspConfig,\n NativeEventEmitterActions,\n SuspiciousAppInfo,\n PackageInfo,\n} from './definitions';\nimport { Threat } from './definitions';\nimport { getThreatCount, itemsHaveType } from './utils';\n\nconst activeListeners: any[] = [];\n\nconst Freerasp = registerPlugin<FreeraspPlugin>('Freerasp', {});\n\nconst onInvalidCallback = (): void => {\n Freerasp.onInvalidCallback();\n};\n\nconst getThreatIdentifiers = async (): Promise<number[]> => {\n const { ids } = await Freerasp.getThreatIdentifiers();\n if (ids.length !== getThreatCount() || !itemsHaveType(ids, 'number')) {\n onInvalidCallback();\n }\n return ids;\n};\n\nconst getThreatChannelData = async (): Promise<[string, string, string]> => {\n const dataLength = Capacitor.getPlatform() === 'ios' ? 2 : 3;\n const { ids } = await Freerasp.getThreatChannelData();\n if (ids.length !== dataLength || !itemsHaveType(ids, 'string')) {\n onInvalidCallback();\n }\n return ids;\n};\n\nconst prepareMapping = async (): Promise<void> => {\n const newValues = await getThreatIdentifiers();\n const threats = Threat.getValues();\n\n threats.map((threat, index) => {\n threat.value = newValues[index];\n });\n};\n\n// parses base64-encoded malware data to SuspiciousAppInfo[]\nconst parseMalwareData = async (\n data: string[],\n): Promise<SuspiciousAppInfo[]> => {\n return new Promise((resolve, reject) => {\n try {\n const suspiciousAppData = data.map(entry => toSuspiciousAppInfo(entry));\n resolve(suspiciousAppData);\n } catch (error: any) {\n reject(`Parsing app data failed: ${error}`);\n }\n });\n};\n\nconst toSuspiciousAppInfo = (base64Value: string): SuspiciousAppInfo => {\n const data = JSON.parse(atob(base64Value));\n const packageInfo = data.packageInfo as PackageInfo;\n return { packageInfo, reason: data.reason } as SuspiciousAppInfo;\n};\n\nconst setThreatListeners = async <T extends NativeEventEmitterActions>(\n callbacks: T & Record<Exclude<keyof T, keyof NativeEventEmitterActions>, []>,\n): Promise<void> => {\n const [channel, key, malwareKey] = await getThreatChannelData();\n await prepareMapping();\n\n await Freerasp.addListener(channel, async (event: any) => {\n if (event[key] === undefined) {\n onInvalidCallback();\n }\n switch (event[key]) {\n case Threat.PrivilegedAccess.value:\n callbacks.privilegedAccess?.();\n break;\n case Threat.Debug.value:\n callbacks.debug?.();\n break;\n case Threat.Simulator.value:\n callbacks.simulator?.();\n break;\n case Threat.AppIntegrity.value:\n callbacks.appIntegrity?.();\n break;\n case Threat.UnofficialStore.value:\n callbacks.unofficialStore?.();\n break;\n case Threat.Hooks.value:\n callbacks.hooks?.();\n break;\n case Threat.DeviceBinding.value:\n callbacks.deviceBinding?.();\n break;\n case Threat.Passcode.value:\n callbacks.passcode?.();\n break;\n case Threat.SecureHardwareNotAvailable.value:\n callbacks.secureHardwareNotAvailable?.();\n break;\n case Threat.ObfuscationIssues.value:\n callbacks.obfuscationIssues?.();\n break;\n case Threat.DeviceID.value:\n callbacks.deviceID?.();\n break;\n case Threat.DevMode.value:\n callbacks.devMode?.();\n break;\n case Threat.SystemVPN.value:\n callbacks.systemVPN?.();\n break;\n case Threat.Malware.value:\n callbacks.malware?.(await parseMalwareData(event[malwareKey]));\n break;\n case Threat.ADBEnabled.value:\n callbacks.adbEnabled?.();\n break;\n case Threat.Screenshot.value:\n callbacks.screenshot?.();\n break;\n case Threat.ScreenRecording.value:\n callbacks.screenRecording?.();\n break;\n default:\n onInvalidCallback();\n break;\n }\n });\n};\n\nconst removeThreatListeners = (): void => {\n activeListeners.forEach(listener => listener.remove());\n};\n\nconst startFreeRASP = async <T extends NativeEventEmitterActions>(\n config: FreeraspConfig,\n reactions: T & Record<Exclude<keyof T, keyof NativeEventEmitterActions>, []>,\n): Promise<boolean> => {\n await setThreatListeners(reactions);\n try {\n const { started } = await Freerasp.talsecStart({ config });\n return started;\n } catch (e: any) {\n console.error(`${e.code}: ${e.message}`);\n return Promise.reject(`${e.code}: ${e.message}`);\n }\n};\n\nconst addToWhitelist = async (packageName: string): Promise<boolean> => {\n if (Capacitor.getPlatform() === 'ios') {\n return Promise.reject('Malware detection not available on iOS');\n }\n const { result } = await Freerasp.addToWhitelist({ packageName });\n return result;\n};\n\nconst getAppIcon = async (packageName: string): Promise<string> => {\n if (Capacitor.getPlatform() === 'ios') {\n return Promise.reject(\n 'App icon retrieval for Malware detection not available on iOS',\n );\n }\n const { result } = await Freerasp.getAppIcon({ packageName });\n return result;\n};\n\nconst blockScreenCapture = async (enable: boolean): Promise<boolean> => {\n if (Capacitor.getPlatform() === 'ios') {\n return Promise.reject('Block Screen Capture is not available on iOS');\n }\n const { result } = await Freerasp.blockScreenCapture({ enable });\n return result;\n};\n\nconst isScreenCaptureBlocked = async (): Promise<boolean> => {\n if (Capacitor.getPlatform() === 'ios') {\n return Promise.reject('Screen Capture Status is not available on iOS');\n }\n const { result } = await Freerasp.isScreenCaptureBlocked();\n return result;\n};\n\nexport * from './definitions';\nexport {\n Freerasp,\n startFreeRASP,\n setThreatListeners,\n removeThreatListeners,\n addToWhitelist,\n getAppIcon,\n blockScreenCapture,\n isScreenCaptureBlocked,\n};\n"]}