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.
- package/CHANGELOG.md +56 -2
- package/README.md +7 -9
- package/android/build.gradle +4 -1
- package/android/src/main/java/com/freeraspreactnative/FreeraspReactNativeModule.kt +49 -4
- package/android/src/main/java/com/freeraspreactnative/FreeraspThreatHandler.kt +9 -1
- package/android/src/main/java/com/freeraspreactnative/Threat.kt +5 -1
- package/android/src/main/java/com/freeraspreactnative/models/RNSuspiciousAppInfo.kt +25 -0
- package/android/src/main/java/com/freeraspreactnative/utils/Extensions.kt +116 -0
- package/android/src/main/java/com/freeraspreactnative/utils/Utils.kt +82 -0
- package/example/assets/arrow-down.png +0 -0
- package/example/assets/arrow-up.png +0 -0
- package/example/ios/FreeraspReactNativeExample.xcodeproj/project.pbxproj +45 -45
- package/example/src/App.tsx +66 -3
- package/example/src/DemoApp.tsx +16 -2
- package/example/src/MalwareItem.tsx +158 -0
- package/example/src/MalwareModal.tsx +126 -0
- package/example/src/checks.ts +2 -0
- package/example/src/styles.ts +1 -0
- package/ios/TalsecRuntime.xcframework/_CodeSignature/CodeDirectory +0 -0
- package/ios/TalsecRuntime.xcframework/_CodeSignature/CodeRequirements +0 -0
- package/ios/TalsecRuntime.xcframework/_CodeSignature/CodeRequirements-1 +0 -0
- package/ios/TalsecRuntime.xcframework/_CodeSignature/CodeResources +60 -60
- package/ios/TalsecRuntime.xcframework/_CodeSignature/CodeSignature +0 -0
- package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/CurlWrapper.h +1 -1
- package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/TalsecRuntime-Swift.h +1 -1
- package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/curl.h +7 -7
- package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/multi.h +4 -4
- package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/options.h +1 -1
- package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Headers/urlapi.h +1 -1
- package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Info.plist +0 -0
- package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios.abi.json +135 -135
- package/ios/TalsecRuntime.xcframework/ios-arm64/TalsecRuntime.framework/TalsecRuntime +0 -0
- package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/CurlWrapper.h +1 -1
- package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/TalsecRuntime-Swift.h +2 -2
- package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/curl.h +7 -7
- package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/multi.h +4 -4
- package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/options.h +1 -1
- package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Headers/urlapi.h +1 -1
- package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Info.plist +0 -0
- package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/arm64-apple-ios-simulator.abi.json +135 -135
- package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/Modules/TalsecRuntime.swiftmodule/x86_64-apple-ios-simulator.abi.json +135 -135
- package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/TalsecRuntime +0 -0
- package/ios/TalsecRuntime.xcframework/ios-arm64_x86_64-simulator/TalsecRuntime.framework/_CodeSignature/CodeResources +21 -21
- package/lib/commonjs/index.js +66 -19
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/{definitions.js → threat.js} +4 -2
- package/lib/commonjs/threat.js.map +1 -0
- package/lib/commonjs/types.js +2 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/commonjs/utils.js +2 -2
- package/lib/commonjs/utils.js.map +1 -1
- package/lib/module/index.js +33 -5
- package/lib/module/index.js.map +1 -1
- package/lib/module/{definitions.js → threat.js} +4 -2
- package/lib/module/threat.js.map +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils.js +1 -1
- package/lib/module/utils.js.map +1 -1
- package/lib/typescript/src/index.d.ts +3 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/threat.d.ts +21 -0
- package/lib/typescript/src/threat.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +51 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/package.json +3 -24
- package/plugin/build/index.d.ts +0 -1
- package/src/index.tsx +38 -8
- package/src/{definitions.ts → threat.ts} +4 -30
- package/src/types.ts +56 -0
- package/src/utils.ts +1 -1
- package/android/src/main/java/com/freeraspreactnative/Utils.kt +0 -40
- package/lib/commonjs/definitions.js.map +0 -1
- package/lib/module/definitions.js.map +0 -1
- package/lib/typescript/src/definitions.d.ts +0 -47
- 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
|
|
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.
|
package/android/build.gradle
CHANGED
|
@@ -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 "
|
|
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
|
-
|
|
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(
|
|
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
|