freerasp-react-native 3.9.3 → 3.11.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 (76) hide show
  1. package/CHANGELOG.md +56 -2
  2. package/README.md +7 -9
  3. package/android/build.gradle +4 -1
  4. package/android/src/main/java/com/freeraspreactnative/FreeraspReactNativeModule.kt +49 -4
  5. package/android/src/main/java/com/freeraspreactnative/FreeraspThreatHandler.kt +9 -1
  6. package/android/src/main/java/com/freeraspreactnative/Threat.kt +5 -1
  7. package/android/src/main/java/com/freeraspreactnative/models/RNSuspiciousAppInfo.kt +25 -0
  8. package/android/src/main/java/com/freeraspreactnative/utils/Extensions.kt +116 -0
  9. package/android/src/main/java/com/freeraspreactnative/utils/Utils.kt +82 -0
  10. package/example/assets/arrow-down.png +0 -0
  11. package/example/assets/arrow-up.png +0 -0
  12. package/example/ios/FreeraspReactNativeExample.xcodeproj/project.pbxproj +45 -45
  13. package/example/src/App.tsx +66 -3
  14. package/example/src/DemoApp.tsx +16 -2
  15. package/example/src/MalwareItem.tsx +158 -0
  16. package/example/src/MalwareModal.tsx +126 -0
  17. package/example/src/checks.ts +2 -0
  18. package/example/src/styles.ts +1 -0
  19. package/ios/TalsecRuntime.xcframework/_CodeSignature/CodeDirectory +0 -0
  20. package/ios/TalsecRuntime.xcframework/_CodeSignature/CodeRequirements +0 -0
  21. package/ios/TalsecRuntime.xcframework/_CodeSignature/CodeRequirements-1 +0 -0
  22. package/ios/TalsecRuntime.xcframework/_CodeSignature/CodeResources +60 -60
  23. package/ios/TalsecRuntime.xcframework/_CodeSignature/CodeSignature +0 -0
  24. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/CurlWrapper.h +1 -1
  25. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/TalsecRuntime-Swift.h +1 -1
  26. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/curl.h +7 -7
  27. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/multi.h +4 -4
  28. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/options.h +1 -1
  29. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/urlapi.h +1 -1
  30. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Info.plist +0 -0
  31. package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios.abi.json +135 -135
  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 +2 -2
  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 +135 -135
  41. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/x86_64-apple-ios-simulator.abi.json +135 -135
  42. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/TalsecRuntime +0 -0
  43. package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/_CodeSignature/CodeResources +21 -21
  44. package/lib/commonjs/index.js +66 -19
  45. package/lib/commonjs/index.js.map +1 -1
  46. package/lib/commonjs/{definitions.js → threat.js} +4 -2
  47. package/lib/commonjs/threat.js.map +1 -0
  48. package/lib/commonjs/types.js +2 -0
  49. package/lib/commonjs/types.js.map +1 -0
  50. package/lib/commonjs/utils.js +2 -2
  51. package/lib/commonjs/utils.js.map +1 -1
  52. package/lib/module/index.js +33 -5
  53. package/lib/module/index.js.map +1 -1
  54. package/lib/module/{definitions.js → threat.js} +4 -2
  55. package/lib/module/threat.js.map +1 -0
  56. package/lib/module/types.js +2 -0
  57. package/lib/module/types.js.map +1 -0
  58. package/lib/module/utils.js +1 -1
  59. package/lib/module/utils.js.map +1 -1
  60. package/lib/typescript/src/index.d.ts +3 -1
  61. package/lib/typescript/src/index.d.ts.map +1 -1
  62. package/lib/typescript/src/threat.d.ts +21 -0
  63. package/lib/typescript/src/threat.d.ts.map +1 -0
  64. package/lib/typescript/src/types.d.ts +51 -0
  65. package/lib/typescript/src/types.d.ts.map +1 -0
  66. package/package.json +3 -24
  67. package/plugin/build/index.d.ts +0 -1
  68. package/src/index.tsx +38 -8
  69. package/src/{definitions.ts → threat.ts} +4 -30
  70. package/src/types.ts +56 -0
  71. package/src/utils.ts +1 -1
  72. package/android/src/main/java/com/freeraspreactnative/Utils.kt +0 -40
  73. package/lib/commonjs/definitions.js.map +0 -1
  74. package/lib/module/definitions.js.map +0 -1
  75. package/lib/typescript/src/definitions.d.ts +0 -47
  76. package/lib/typescript/src/definitions.d.ts.map +0 -1
package/CHANGELOG.md CHANGED
@@ -5,7 +5,56 @@ 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
+ ## [3.11.0] - 2024-11-19
9
+
10
+ ### React Native
11
+
12
+ #### Added
13
+
14
+ - Added `adbEnabled` callback, which allows you to detect USB debugging option enabled in the developer settings on the device
15
+
16
+ ### Android
17
+
18
+ #### Added
19
+
20
+ - ADB detection feature
21
+
22
+ ## [3.10.0] - 2024-11-15
23
+
24
+ - Android SDK version: 12.0.0
25
+ - iOS SDK version: 6.6.3
26
+
27
+ ### React Native
28
+
29
+ #### Added
30
+
31
+ - Added configuration fields for malware detection
32
+
33
+ ### Android
34
+
35
+ #### Added
36
+
37
+ - New feature: **malware detection** as a new callback for enhanced app security
38
+
39
+ #### Fixed
40
+
41
+ - Refactoring Magisk checks in the root detection
42
+
43
+ ### iOS
44
+
45
+ #### Added
46
+
47
+ - Enhanced security with **[Serotonin Jailbreak](https://github.com/SerotoninApp/Serotonin) Detection** to identify compromised devices.
48
+
49
+ #### Changed
50
+
51
+ - Updated SDK code signing; it will now be signed with:
52
+ - Team ID: PBDDS45LQS
53
+ - Team Name: Lynx SFT s.r.o.
54
+
8
55
  ## [3.9.3] - 2024-10-28
56
+ - Android SDK version: 11.1.3
57
+ - iOS SDK version: 6.6.1
9
58
 
10
59
  ### iOS
11
60
 
@@ -13,6 +62,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
13
62
  - Renewed the signing certificate
14
63
 
15
64
  ## [3.9.2] - 2024-10-18
65
+ - Android SDK version: 11.1.3
66
+ - iOS SDK version: 6.6.0
67
+
68
+ - Android SDK version: 11.1.3
69
+ - iOS SDK version: 6.6.0
16
70
 
17
71
  ### Android
18
72
 
@@ -47,7 +101,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
47
101
 
48
102
  ### Android
49
103
 
50
- #### Added
104
+ #### Added
51
105
 
52
106
  - Added the auditing of the internal execution for the future check optimization and overall security improvements.
53
107
 
@@ -65,7 +119,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
65
119
 
66
120
  ### iOS
67
121
 
68
- #### Added
122
+ #### Added
69
123
 
70
124
  - [Dopamine](https://github.com/opa334/Dopamine) jailbreak detection.
71
125
 
package/README.md CHANGED
@@ -10,7 +10,6 @@ freeRASP for React Native is a mobile in-app protection and security monitoring
10
10
 
11
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
-
14
13
  # Overview
15
14
 
16
15
  The freeRASP is available for Flutter, Cordova, React Native, Android, and iOS developers. We encourage community contributions, investigations of attack cases, joint data research, and other activities aiming to make better app security and app safety for end-users.
@@ -29,7 +28,7 @@ Key features are the detection and prevention of
29
28
  - Untrusted installation method
30
29
  - App/Device (un)binding
31
30
 
32
- Additional freeRASP features include low latency, easy integration and a weekly [Security Report](https://docs.talsec.app/freerasp/security-report ) containing detailed information about detected incidents and potential threats, summarizing the state of your app security.
31
+ Additional freeRASP features include low latency, easy integration and a weekly [Security Report](https://docs.talsec.app/freerasp/security-report) containing detailed information about detected incidents and potential threats, summarizing the state of your app security.
33
32
 
34
33
  The commercial version provides a top-notch protection level, extra features, support and maintenance. One of the most valued commercial features is AppiCrypt® - App Integrity Cryptogram.
35
34
 
@@ -46,6 +45,11 @@ Learn more about commercial features at [https://talsec.app](https://talsec.app)
46
45
 
47
46
  Learn more about freemium freeRASP features at [GitHub main repository](https://github.com/talsec/Free-RASP-Community).
48
47
 
48
+ ## :radioactive: freeMalwareDetection
49
+ **freeMalwareDetection** is a powerful feature designed to enhance the security of your Android application by quickly and efficiently scanning for malicious or suspicious applications (e.g. Android malware) based on various blacklists and security policies. It helps to detect apps with suspicious package names, hashes, or potentially dangerous permissions.
50
+
51
+ After the integration of freeRASP, make sure you visit the [freeMalwareDetection](https://docs.talsec.app/freemalwaredetection) repository to learn more about this feature!
52
+
49
53
  # :book: Discover the Official freeRASP Documentation
50
54
 
51
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,12 +60,6 @@ For integrating freeRASP on the React Native platform, be sure to follow all the
56
60
 
57
61
  Be sure to bookmark it and stay informed! :books: :sparkles:.
58
62
 
59
- ## :scroll: Reference to Legacy Documentation
60
-
61
- If you have any suggestions for improvement or notice anything that could be clarified in the new GitBook documentation, please open an issue. Your feedback helps us maintain high-quality resources for all users.
62
-
63
- For information on older integration methods, you can refer to the [freeRASP wiki](https://github.com/talsec/Free-RASP-ReactNative/wiki), which includes comprehensive legacy details and guidance. Additionally, the old integration can be found when you checkout to a specific tag. Your input is invaluable in helping us improve our resources and provide even better support for your needs.
64
-
65
63
  # :rocket: What's New and Changelog
66
64
 
67
65
  Stay informed and make the most of freeRASP by checking out [What's New and Changelog](https://docs.talsec.app/freerasp/whats-new-and-changelog)! Here, you’ll discover the latest features, enhancements, and bug fixes we’ve implemented to improve your experience across all platforms, including Android, iOS, Flutter, React Native, Capacitor, and Cordova.
@@ -75,4 +73,4 @@ If you have any ideas for improvements, feel free to [raise an issue](https://gi
75
73
  You can check out the project board [here](https://github.com/orgs/talsec/projects/2).
76
74
 
77
75
  # :page_facing_up: License
78
- This project is provided as freemium software, i.e. there is a fair usage policy that imposes some limitations on the free usage. The SDK software consists of open-source and binary parts, which is the property of Talsec. The open-source part is licensed under the MIT License - see the LICENSE file for details.
76
+ This project is provided as freemium software, i.e. there is a fair usage policy that imposes some limitations on the free usage. The SDK software consists of open-source and binary parts, which is the property of Talsec. The open-source part is licensed under the MIT License - see the LICENSE file for details.
@@ -11,6 +11,7 @@ buildscript {
11
11
  classpath "com.android.tools.build:gradle:7.2.1"
12
12
  // noinspection DifferentKotlinGradleVersion
13
13
  classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14
+ classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
14
15
  }
15
16
  }
16
17
 
@@ -20,6 +21,7 @@ def isNewArchitectureEnabled() {
20
21
 
21
22
  apply plugin: "com.android.library"
22
23
  apply plugin: "kotlin-android"
24
+ apply plugin: 'kotlinx-serialization'
23
25
 
24
26
  if (isNewArchitectureEnabled()) {
25
27
  apply plugin: "com.facebook.react"
@@ -87,7 +89,8 @@ dependencies {
87
89
  //noinspection GradleDynamicVersion
88
90
  implementation "com.facebook.react:react-native:$react_native_version"
89
91
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
90
- implementation "com.aheaditec.talsec.security:TalsecSecurity-Community-ReactNative:11.1.3"
92
+ implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1"
93
+ implementation "com.aheaditec.talsec.security:TalsecSecurity-Community-ReactNative:13.0.0"
91
94
  }
92
95
 
93
96
  if (isNewArchitectureEnabled()) {
@@ -1,5 +1,6 @@
1
1
  package com.freeraspreactnative
2
2
 
3
+ import com.aheaditec.talsec_security.security.api.SuspiciousAppInfo
3
4
  import com.aheaditec.talsec_security.security.api.Talsec
4
5
  import com.aheaditec.talsec_security.security.api.TalsecConfig
5
6
  import com.aheaditec.talsec_security.security.api.ThreatListener
@@ -12,8 +13,14 @@ import com.facebook.react.bridge.ReadableMap
12
13
  import com.facebook.react.bridge.UiThreadUtil.runOnUiThread
13
14
  import com.facebook.react.bridge.WritableArray
14
15
  import com.facebook.react.modules.core.DeviceEventManagerModule
15
-
16
- class FreeraspReactNativeModule(val reactContext: ReactApplicationContext) :
16
+ import com.freeraspreactnative.utils.getArraySafe
17
+ import com.freeraspreactnative.utils.getBooleanSafe
18
+ import com.freeraspreactnative.utils.getMapThrowing
19
+ import com.freeraspreactnative.utils.getNestedArraySafe
20
+ import com.freeraspreactnative.utils.getStringThrowing
21
+ import com.freeraspreactnative.utils.toEncodedWritableArray
22
+
23
+ class FreeraspReactNativeModule(private val reactContext: ReactApplicationContext) :
17
24
  ReactContextBaseJavaModule(reactContext) {
18
25
 
19
26
  private val listener = ThreatListener(FreeraspThreatHandler, FreeraspThreatHandler)
@@ -42,8 +49,7 @@ class FreeraspReactNativeModule(val reactContext: ReactApplicationContext) :
42
49
 
43
50
  promise.resolve("freeRASP started")
44
51
 
45
- }
46
- catch (e: Exception) {
52
+ } catch (e: Exception) {
47
53
  promise.reject("TalsecInitializationError", e.message, e)
48
54
  }
49
55
  }
@@ -65,6 +71,7 @@ class FreeraspReactNativeModule(val reactContext: ReactApplicationContext) :
65
71
  val channelData: WritableArray = Arguments.createArray()
66
72
  channelData.pushString(THREAT_CHANNEL_NAME)
67
73
  channelData.pushString(THREAT_CHANNEL_KEY)
74
+ channelData.pushString(MALWARE_CHANNEL_KEY)
68
75
  promise.resolve(channelData)
69
76
  }
70
77
 
@@ -87,6 +94,15 @@ class FreeraspReactNativeModule(val reactContext: ReactApplicationContext) :
87
94
  // Remove upstream listeners, stop unnecessary background tasks
88
95
  }
89
96
 
97
+ /**
98
+ * Method to add apps to Malware whitelist, so they don't get flagged as malware
99
+ */
100
+ @ReactMethod
101
+ fun addToWhitelist(packageName: String, promise: Promise) {
102
+ Talsec.addToWhitelist(reactContext, packageName)
103
+ promise.resolve(true)
104
+ }
105
+
90
106
  private fun buildTalsecConfig(config: ReadableMap): TalsecConfig {
91
107
  val androidConfig = config.getMapThrowing("androidConfig")
92
108
  val packageName = androidConfig.getStringThrowing("packageName")
@@ -97,6 +113,14 @@ class FreeraspReactNativeModule(val reactContext: ReactApplicationContext) :
97
113
  .supportedAlternativeStores(androidConfig.getArraySafe("supportedAlternativeStores"))
98
114
  .prod(config.getBooleanSafe("isProd"))
99
115
 
116
+ if (androidConfig.hasKey("malwareConfig")) {
117
+ val malwareConfig = androidConfig.getMapThrowing("malwareConfig")
118
+ talsecBuilder.whitelistedInstallationSources(malwareConfig.getArraySafe("whitelistedInstallationSources"))
119
+ talsecBuilder.blacklistedHashes(malwareConfig.getArraySafe("blacklistedHashes"))
120
+ talsecBuilder.blacklistedPackageNames(malwareConfig.getArraySafe("blacklistedPackageNames"))
121
+ talsecBuilder.suspiciousPermissions(malwareConfig.getNestedArraySafe("suspiciousPermissions"))
122
+ }
123
+
100
124
  return talsecBuilder.build()
101
125
  }
102
126
 
@@ -106,6 +130,8 @@ class FreeraspReactNativeModule(val reactContext: ReactApplicationContext) :
106
130
  .toString() // name of the channel over which threat callbacks are sent
107
131
  val THREAT_CHANNEL_KEY = (10000..999999999).random()
108
132
  .toString() // key of the argument map under which threats are expected
133
+ val MALWARE_CHANNEL_KEY = (10000..999999999).random()
134
+ .toString() // key of the argument map under which malware data is expected
109
135
  private lateinit var appReactContext: ReactApplicationContext
110
136
  private fun notifyListeners(threat: Threat) {
111
137
  val params = Arguments.createMap()
@@ -114,11 +140,30 @@ class FreeraspReactNativeModule(val reactContext: ReactApplicationContext) :
114
140
  .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
115
141
  .emit(THREAT_CHANNEL_NAME, params)
116
142
  }
143
+
144
+ /**
145
+ * Sends malware detected event to React Native
146
+ */
147
+ private fun notifyMalware(suspiciousApps: MutableList<SuspiciousAppInfo>) {
148
+ val params = Arguments.createMap()
149
+ params.putInt(THREAT_CHANNEL_KEY, Threat.Malware.value)
150
+ params.putArray(
151
+ MALWARE_CHANNEL_KEY, suspiciousApps.toEncodedWritableArray(appReactContext)
152
+ )
153
+
154
+ appReactContext
155
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
156
+ .emit(THREAT_CHANNEL_NAME, params)
157
+ }
117
158
  }
118
159
 
119
160
  internal object ThreatListener : FreeraspThreatHandler.TalsecReactNative {
120
161
  override fun threatDetected(threatType: Threat) {
121
162
  notifyListeners(threatType)
122
163
  }
164
+
165
+ override fun malwareDetected(suspiciousApps: MutableList<SuspiciousAppInfo>) {
166
+ notifyMalware(suspiciousApps)
167
+ }
123
168
  }
124
169
  }
@@ -39,7 +39,9 @@ internal object FreeraspThreatHandler : ThreatListener.ThreatDetected, ThreatLis
39
39
  listener?.threatDetected(Threat.ObfuscationIssues)
40
40
  }
41
41
 
42
- override fun onMalwareDetected(p0: MutableList<SuspiciousAppInfo>?) {}
42
+ override fun onMalwareDetected(suspiciousAppInfos: MutableList<SuspiciousAppInfo>?) {
43
+ listener?.malwareDetected(suspiciousAppInfos ?: mutableListOf())
44
+ }
43
45
 
44
46
  override fun onUnlockedDeviceDetected() {
45
47
  listener?.threatDetected(Threat.Passcode)
@@ -53,11 +55,17 @@ internal object FreeraspThreatHandler : ThreatListener.ThreatDetected, ThreatLis
53
55
  listener?.threatDetected(Threat.DevMode)
54
56
  }
55
57
 
58
+ override fun onADBEnabledDetected() {
59
+ listener?.threatDetected(Threat.ADBEnabled)
60
+ }
61
+
56
62
  override fun onSystemVPNDetected() {
57
63
  listener?.threatDetected(Threat.SystemVPN)
58
64
  }
59
65
 
60
66
  internal interface TalsecReactNative {
61
67
  fun threatDetected(threatType: Threat)
68
+
69
+ fun malwareDetected(suspiciousApps: MutableList<SuspiciousAppInfo>)
62
70
  }
63
71
  }
@@ -23,6 +23,8 @@ internal sealed class Threat(val value: Int) {
23
23
  object ObfuscationIssues : Threat((10000..999999999).random())
24
24
  object SystemVPN : Threat((10000..999999999).random())
25
25
  object DevMode : Threat((10000..999999999).random())
26
+ object Malware : Threat((10000..999999999).random())
27
+ object ADBEnabled : Threat((10000..999999999).random())
26
28
 
27
29
  companion object {
28
30
  internal fun getThreatValues(): WritableArray {
@@ -39,7 +41,9 @@ internal sealed class Threat(val value: Int) {
39
41
  DeviceBinding.value,
40
42
  UnofficialStore.value,
41
43
  ObfuscationIssues.value,
42
- DevMode.value
44
+ DevMode.value,
45
+ Malware.value,
46
+ ADBEnabled.value
43
47
  )
44
48
  )
45
49
  }
@@ -0,0 +1,25 @@
1
+ package com.freeraspreactnative.models
2
+
3
+ import kotlinx.serialization.Serializable
4
+
5
+
6
+ /**
7
+ * Simplified, serializable wrapper for Talsec's SuspiciousAppInfo
8
+ */
9
+ @Serializable
10
+ data class RNSuspiciousAppInfo(
11
+ val packageInfo: RNPackageInfo,
12
+ val reason: String,
13
+ )
14
+
15
+ /**
16
+ * Simplified, serializable wrapper for Android's PackageInfo
17
+ */
18
+ @Serializable
19
+ data class RNPackageInfo(
20
+ val packageName: String,
21
+ val appName: String?,
22
+ val version: String?,
23
+ val appIcon: String?,
24
+ val installerStore: String?
25
+ )
@@ -0,0 +1,116 @@
1
+ package com.freeraspreactnative.utils
2
+
3
+ import android.content.pm.PackageInfo
4
+ import android.util.Base64
5
+ import android.util.Log
6
+ import com.aheaditec.talsec_security.security.api.SuspiciousAppInfo
7
+ import com.facebook.react.bridge.Arguments
8
+ import com.facebook.react.bridge.ReactContext
9
+ import com.facebook.react.bridge.ReadableArray
10
+ import com.facebook.react.bridge.ReadableMap
11
+ import com.facebook.react.bridge.WritableArray
12
+ import com.freeraspreactnative.exceptions.TalsecException
13
+ import com.freeraspreactnative.models.RNPackageInfo
14
+ import com.freeraspreactnative.models.RNSuspiciousAppInfo
15
+ import kotlinx.serialization.encodeToString
16
+ import kotlinx.serialization.json.Json
17
+ import org.json.JSONException
18
+
19
+
20
+ internal fun ReadableMap.getMapThrowing(key: String): ReadableMap {
21
+ return this.getMap(key) ?: throw TalsecException("Key missing in configuration: $key")
22
+ }
23
+
24
+ internal fun ReadableMap.getStringThrowing(key: String): String {
25
+ return this.getString(key) ?: throw TalsecException("Key missing in configuration: $key")
26
+ }
27
+
28
+ internal fun ReadableMap.getBooleanSafe(key: String, defaultValue: Boolean = true): Boolean {
29
+ if (this.hasKey(key)) {
30
+ return this.getBoolean(key)
31
+ }
32
+ return defaultValue
33
+ }
34
+
35
+ private inline fun <reified T> ReadableArray.toPrimitiveArray(): Array<T> {
36
+ val output = mutableListOf<T>()
37
+
38
+ for (i in 0 until this.size()) {
39
+ val element: T? = when (T::class) {
40
+ String::class -> this.getString(i) as T?
41
+ Int::class -> this.getInt(i) as T?
42
+ Double::class -> this.getDouble(i) as T?
43
+ Boolean::class -> this.getBoolean(i) as T?
44
+ else -> throw JSONException("Cannot parse JSON array - unsupported type")
45
+ }
46
+ element?.let(output::add)
47
+ }
48
+ return output.toTypedArray()
49
+ }
50
+
51
+ internal fun ReadableMap.getArraySafe(key: String): Array<String> {
52
+ if (this.hasKey(key)) {
53
+ val inputArray = this.getArray(key)!!
54
+ return inputArray.toPrimitiveArray()
55
+ }
56
+ return arrayOf()
57
+ }
58
+
59
+ internal fun ReadableMap.getNestedArraySafe(key: String): Array<Array<String>> {
60
+ val outArray = mutableListOf<Array<String>>()
61
+ if (this.hasKey(key)) {
62
+ val inputArray = this.getArray(key)!!
63
+ for (i in 0 until inputArray.size()) {
64
+ outArray.add(inputArray.getArray(i).toPrimitiveArray())
65
+ }
66
+ }
67
+ return outArray.toTypedArray()
68
+ }
69
+
70
+
71
+ /**
72
+ * Converts the Talsec's SuspiciousAppInfo to React Native equivalent
73
+ */
74
+ internal fun SuspiciousAppInfo.toRNSuspiciousAppInfo(context: ReactContext): RNSuspiciousAppInfo {
75
+ return RNSuspiciousAppInfo(
76
+ packageInfo = this.packageInfo.toRNPackageInfo(context),
77
+ reason = this.reason,
78
+ )
79
+ }
80
+
81
+ /**
82
+ * Converts the Android's PackageInfo to React Native equivalent
83
+ */
84
+ internal fun PackageInfo.toRNPackageInfo(context: ReactContext): RNPackageInfo {
85
+ return RNPackageInfo(
86
+ packageName = this.packageName,
87
+ appName = Utils.getAppName(context, this.applicationInfo),
88
+ version = this.versionName,
89
+ appIcon = Utils.getAppIconAsBase64String(context, this.packageName),
90
+ installerStore = Utils.getInstallationSource(context, this.packageName)
91
+ )
92
+ }
93
+
94
+ /**
95
+ * Convert the Talsec's SuspiciousAppInfo to base64-encoded json array,
96
+ * which can be then sent to React Native
97
+ */
98
+ internal fun MutableList<SuspiciousAppInfo>.toEncodedWritableArray(context: ReactContext): WritableArray {
99
+ val output = Arguments.createArray()
100
+ this.forEach { suspiciousAppInfo ->
101
+ val rnSuspiciousAppInfo = suspiciousAppInfo.toRNSuspiciousAppInfo(context)
102
+ try {
103
+ val encodedAppInfo =
104
+ Base64.encodeToString(
105
+ Json.encodeToString(rnSuspiciousAppInfo).toByteArray(),
106
+ Base64.DEFAULT
107
+ )
108
+ output.pushString(encodedAppInfo)
109
+ } catch (e: Exception) {
110
+ Log.e("Talsec", "Could not serialize suspicious app data: ${e.message}")
111
+ }
112
+
113
+ }
114
+ return output
115
+ }
116
+
@@ -0,0 +1,82 @@
1
+ package com.freeraspreactnative.utils
2
+
3
+ import android.content.pm.ApplicationInfo
4
+ import android.graphics.Bitmap
5
+ import android.graphics.Canvas
6
+ import android.graphics.drawable.BitmapDrawable
7
+ import android.os.Build
8
+ import android.util.Base64
9
+ import android.util.Log
10
+ import com.facebook.react.bridge.ReactContext
11
+ import java.io.ByteArrayOutputStream
12
+
13
+
14
+ internal object Utils {
15
+
16
+ private fun compressBitmap(bitmap: Bitmap): String {
17
+ val byteArrayOutputStream = ByteArrayOutputStream()
18
+ bitmap.compress(Bitmap.CompressFormat.PNG, 10, byteArrayOutputStream)
19
+ val byteArray = byteArrayOutputStream.toByteArray()
20
+ return Base64.encodeToString(byteArray, Base64.NO_WRAP)
21
+ }
22
+
23
+ /**
24
+ * Retrieves human-readable application name
25
+ */
26
+ internal fun getAppName(context: ReactContext, applicationInfo: ApplicationInfo?): String? {
27
+ return applicationInfo?.let { context.packageManager.getApplicationLabel(it) as String }
28
+ }
29
+
30
+ /**
31
+ * Retrieves app icon for the given package name as Drawable, transforms it to Bitmap,
32
+ * compresses to PNG and finally encodes the data to Base64
33
+ * @param context React Native context
34
+ * @param packageName package name for which icon should be retrieved
35
+ * @return Base-64 encoded string
36
+ */
37
+ internal fun getAppIconAsBase64String(context: ReactContext, packageName: String): String? {
38
+ try {
39
+ val drawable = context.packageManager.getApplicationIcon(packageName)
40
+
41
+ if (drawable is BitmapDrawable && drawable.bitmap != null) {
42
+ return compressBitmap(drawable.bitmap)
43
+ }
44
+
45
+ if (drawable.intrinsicWidth > 0 && drawable.intrinsicHeight > 0) {
46
+ val bitmap = Bitmap.createBitmap(
47
+ drawable.intrinsicWidth,
48
+ drawable.intrinsicHeight,
49
+ Bitmap.Config.ARGB_8888
50
+ )
51
+ val canvas = Canvas(bitmap)
52
+ drawable.setBounds(0, 0, canvas.width, canvas.height)
53
+ drawable.draw(canvas)
54
+ return compressBitmap(bitmap)
55
+ }
56
+ return null
57
+ } catch (e: Exception) {
58
+ Log.e("Talsec", "Could not retrieve app icon for ${packageName}: ${e.message}")
59
+ return null
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Retrieves installation source for the given package name
65
+ * @param context React Native context
66
+ * @param packageName package name for which installation source should be retrieved
67
+ * @return Installation source package name
68
+ */
69
+ @Suppress("DEPRECATION")
70
+ internal fun getInstallationSource(context: ReactContext, packageName: String): String? {
71
+ return try {
72
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
73
+ context.packageManager.getInstallSourceInfo(packageName).installingPackageName
74
+ } else {
75
+ context.packageManager.getInstallerPackageName(packageName)
76
+ }
77
+ } catch (e: Exception) {
78
+ Log.e("Talsec", "Could not retrieve app installation source for ${packageName}: ${e.message}")
79
+ null
80
+ }
81
+ }
82
+ }
Binary file
Binary file