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