UNPKG

react-native-malwarelytics

Version:

Malwarelytics for React Native protects your banking or fintech app from a broad range of mobile security threats with an industry-leading mobile threat intelligence solution.

248 lines (225 loc) 9.99 kB
// // Copyright 2023 Wultra s.r.o. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions // and limitations under the License. // import type { EmitterSubscription } from "react-native"; import { Platform } from "react-native" import { EventHelper } from "./internal/EventHelper" import { MalwarelyticsModuleIfc, wrapNativeCall } from "./internal/MalwarelyticsModule" import { MalwarelyticsError } from "./MalwarelyticsError" import { SmartProtectionResult } from "./model/antivirus/SmartProtectionResult" import { ApkThreat, ThreatIndex, threatIndexToNumber } from "./model/antivirus/ApkThreat" import { ApkInfo } from "./model/antivirus/Apk" import { ApkThreatEvent } from "./internal/ApkThreatEvent" import { ObservedUpdateInfo } from "./model/antivirus/update/ObservedUpdateInfo" import { UpdateInfo } from "./model/antivirus/update/UpdateInfo" /** * The `MalwarelyticsAntivirus` class provides antivirus functionality from Malwarelytics for Android SDK. * Be aware that you must evaluate whether the funcionality is supported on the platform, by getting * `isSupported` property. All other methods from the class fails with error if antivirus is not supported * on the platform. */ export class MalwarelyticsAntivirus { constructor(eventHelper: EventHelper) { if (Platform.OS == 'android') { this.module = eventHelper.module } this.eventHelper = eventHelper this.isSupported = this.module != undefined } /** * Determine whether the Antivirus module is supported on the platform. */ readonly isSupported: boolean /** * Instance of EventHelper shared with Malwarelytics class. */ private readonly eventHelper: EventHelper /** * Instance of native module interface. */ private readonly module?: MalwarelyticsModuleIfc /** * Object representing a subscription to update events. */ private updateEventSubscription: EmitterSubscription | undefined /** * Object representing a subscription to apk threat events. */ private apkThreatEventSubscription: EmitterSubscription | undefined /** * Test whether antivirus is enabled. */ isEnabled(): Promise<boolean> { return this.withModule(module => module.isAntivirusEnabled()) } /** * Set custom localization to be used when a UI is shown. * This overrides system settings. Use ISO 639-1 language code or `undefined`. * Undefined value will reset the custom setting and the system settings will be used again */ setCustomLocalization(languageCode: string | undefined): Promise<void> { return this.withModule(module => module.setAntivirusLocalization(languageCode)) } /** * Get custom localization currently in use by antivirus. */ getCustomLocalization(): Promise<string | undefined> { return this.withModule(module => module.getAntivirusLocalization()) } /** * Schedules a job that will execute smart protection run. Note that this is asynchronous and * can take some time. * * Note that you can call this function with multiple times, but you'll get the result once the internal * evaluation is finished. * * @param performOnlineUpdate Optional argument to indicate that online update is not desired. If false only local data will be used. */ triggerSmartProtection(performOnlineUpdate: boolean = true): Promise<SmartProtectionResult> { return this.withModule(module => module.triggerSmartProtection(performOnlineUpdate)) } /** * Get information whether smart protection evaluation is already running. */ isSmartProtectionTriggered(): Promise<boolean> { return this.withModule(module => module.isSmartProtectionTriggered()) } /** * Returns list of all applications with the malware evaluation. */ getThreatList(): Promise<ApkThreat[]> { return this.withModule(module => module.getThreatList()) } /** * Returns list of all applications with the malware evaluation higher or equal than specified. * @param minThreatIndex Minimal threat index. * @returns List of all applications with the malware evaluation higher or equal than specified. */ async getFilteredThreatList(minThreatIndex: ThreatIndex): Promise<ApkThreat[]> { const minIndex = threatIndexToNumber(minThreatIndex) return (await this.getThreatList()).filter(item => threatIndexToNumber(item.threatIndex) >= minIndex) } /** * Gets more information for the package name of the application. * * @param packageName Package name of the application * @returns Information about package or `undefined` when no such information is available. */ getApkInfo(packageName: string): Promise<ApkInfo | undefined> { return this.withModule(module => module.getApkInfo(packageName)) } /** * Get information about the last updates. * * Primarily intended for troubleshooting. * * @returns Information about latest update successes and failures. */ getLastUpdateInfo(): Promise<UpdateInfo> { return this.withModule(module => module.getLastUpdateInfo()); } /** Set listener that is triggered when a suggestion update completes. */ async setUpdateListener(listener: MalwarelyticsAndroidUpdateListener): Promise<void> { this.updateEventSubscription?.remove() if (this.module == undefined) { return Promise.reject(new MalwarelyticsError('METHOD_NOT_SUPPORTED', `Method is not supported on ${Platform.OS} platform`)) } this.updateEventSubscription = await this.eventHelper.addListener('Malwarelytics.AV_UPDATE', (data) => { // console.log(`${Platform.OS}: AV_UPDATE event: ${JSON.stringify(data)}`) const oui = data as ObservedUpdateInfo listener.onSuggestionUpdated(oui) }) } /** Remove listener for suggestion updates. */ removeUpdateListener() { this.updateEventSubscription?.remove() this.updateEventSubscription = undefined } /** Set listener that is triggered whan an app is installed/updated/uninstall. */ async setApkThreatListener(listener: MalwarelyticsAndroidApkThreatListener): Promise<void> { this.apkThreatEventSubscription?.remove() if (this.module == undefined) { return Promise.reject(new MalwarelyticsError('METHOD_NOT_SUPPORTED', `Method is not supported on ${Platform.OS} platform`)) } this.apkThreatEventSubscription = await this.eventHelper.addListener('Malwarelytics.AV_APK_THREAT', (data) => { // console.log(`${Platform.OS}: AV_APK_THREAT event: ${JSON.stringify(data)}`) const event = data as ApkThreatEvent switch (event.type) { case "INSTALL": listener.onInstallDetected(event.payload as ApkThreat) break case "UPDATE": listener.onUpdateDetected(event.payload as ApkThreat) break case "UNINSTALL": listener.onUninstallDetected(event.payload as string) break default: console.warn(`${Platform.OS}: Unsupported APK THREAT event ${event.type}`) break } }) } /** Remove listgener for app installs/updates/uninstall. */ removeApkThreatListener() { this.apkThreatEventSubscription?.remove() this.apkThreatEventSubscription = undefined } /** * Execute closure with action with properly acquired instnace to native module. * @param action Action to execute. * @returns Result returned from the action. */ private withModule<T>(action: (nativeModule: MalwarelyticsModuleIfc) => Promise<T>): Promise<T> { if (this.module != undefined) { return wrapNativeCall(this.module, action) } return Promise.reject(new MalwarelyticsError('METHOD_NOT_SUPPORTED', `Method is not supported on ${Platform.OS} platform`)) } } /** Listener for update results. */ export interface MalwarelyticsAndroidUpdateListener { /** * Called when an update was finished regardless of a success or a failure. * * Returned data indicated the update result: * - Successful update: * @see ObservedUpdateInfo.failureReason is null * - Partially successful update: * @see ObservedUpdateInfo.failureReason is not null * and @see ObservedUpdateInfo.updatedApps is not empty * - Failed update: * and @see ObservedUpdateInfo.failureReason is not null * and @see ObservedUpdateInfo.updatedApps is empty */ onSuggestionUpdated(observedUpdateInfo: ObservedUpdateInfo): void; } /** Listener for updates to the apps on the device. */ export interface MalwarelyticsAndroidApkThreatListener { /** * Called whan an app install is detected. * @param apkThread The new threat. */ onInstallDetected(apkThreat: ApkThreat): void; /** * Called when an app update is detected. * @param apkThread The changed threat. */ onUpdateDetected(apkThreat: ApkThreat): void; /** * Called when an app uninstall is detected. * @param packageName The package name of the deleted threat. */ onUninstallDetected(packageName: string): void; }