Skip to content

Commit ef8a899

Browse files
committed
feat(ts): add malware detection
1 parent 69ae21f commit ef8a899

File tree

5 files changed

+87
-14
lines changed

5 files changed

+87
-14
lines changed

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "freerasp-react-native",
3-
"version": "3.9.2",
3+
"version": "3.10.0",
44
"description": "React Native plugin for improving app security and threat monitoring on Android and iOS mobile devices.",
55
"main": "lib/commonjs/index",
66
"module": "lib/module/index",
@@ -12,6 +12,7 @@
1212
"expo:typecheck": "cd plugin && tsc --noEmit",
1313
"lint": "eslint \"**/*.{js,ts,tsx}\"",
1414
"prepack": "bob build && yarn build:plugin",
15+
"build": "bob build",
1516
"example": "yarn --cwd example",
1617
"bootstrap": "yarn example && yarn install && yarn example pods",
1718
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build",
@@ -43,12 +44,16 @@
4344
"publishConfig": {
4445
"registry": "https://registry.npmjs.org/"
4546
},
47+
"dependencies": {
48+
"base-64": "^1.0.0"
49+
},
4650
"devDependencies": {
4751
"@react-native-community/eslint-config": "^3.0.2",
4852
"@release-it/conventional-changelog": "^5.0.0",
4953
"@tsconfig/node-lts": "^20.1.1",
5054
"@types/react": "17.0.21",
5155
"@types/react-native": "0.70.0",
56+
"@types/base-64": "^1.0.2",
5257
"del-cli": "^5.0.0",
5358
"eslint": "^8.4.1",
5459
"eslint-config-prettier": "^8.5.0",

plugin/build/index.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { ConfigPlugin } from '@expo/config-plugins';
21
import { type PluginConfigType } from './pluginConfig';
32
declare const _default: ConfigPlugin<PluginConfigType>;
43
export default _default;

src/definitions.ts

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,44 @@
11
import { Platform } from 'react-native';
22

33
export type TalsecConfig = {
4-
androidConfig?: {
5-
packageName: string;
6-
certificateHashes: string[];
7-
supportedAlternativeStores?: string[];
8-
};
9-
iosConfig?: {
10-
appBundleId: string;
11-
appTeamId: string;
12-
};
4+
androidConfig?: TalsecAndroidConfig;
5+
iosConfig?: TalsecIosConfig;
136
watcherMail: string;
147
isProd?: boolean;
158
};
169

10+
export type TalsecAndroidConfig = {
11+
packageName: string;
12+
certificateHashes: string[];
13+
supportedAlternativeStores?: string[];
14+
malware?: TalsecMalwareConfig;
15+
};
16+
17+
export type TalsecIosConfig = {
18+
appBundleId: string;
19+
appTeamId: string;
20+
};
21+
22+
export type TalsecMalwareConfig = {
23+
blocklistedHashes?: string[];
24+
blocklistedPackageNames?: string[];
25+
blocklistedPermissions?: string[][];
26+
whitelistedInstallationSources?: string[];
27+
};
28+
29+
export type SuspiciousAppInfo = {
30+
packageInfo: PackageInfo;
31+
reason: string;
32+
};
33+
34+
export type PackageInfo = {
35+
packageName: string;
36+
appName?: string;
37+
version?: string;
38+
appIcon?: string;
39+
installerStore?: string;
40+
};
41+
1742
export type NativeEventEmitterActions = {
1843
privilegedAccess?: () => any;
1944
debug?: () => any;
@@ -28,6 +53,7 @@ export type NativeEventEmitterActions = {
2853
obfuscationIssues?: () => any;
2954
devMode?: () => any;
3055
systemVPN?: () => any;
56+
malware?: (suspiciousApps: SuspiciousAppInfo[]) => any;
3157
};
3258

3359
export class Threat {
@@ -46,6 +72,7 @@ export class Threat {
4672
static UnofficialStore = new Threat(0);
4773
static ObfuscationIssues = new Threat(0);
4874
static DevMode = new Threat(0);
75+
static Malware = new Threat(0);
4976

5077
constructor(value: number) {
5178
this.value = value;
@@ -66,6 +93,7 @@ export class Threat {
6693
this.UnofficialStore,
6794
this.ObfuscationIssues,
6895
this.DevMode,
96+
this.Malware,
6997
]
7098
: [
7199
this.AppIntegrity,

src/index.tsx

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@ import { useEffect } from 'react';
22
import {
33
NativeEventEmitter,
44
NativeModules,
5+
Platform,
56
type EmitterSubscription,
67
} from 'react-native';
78
import {
89
Threat,
910
type NativeEventEmitterActions,
11+
type PackageInfo,
12+
type SuspiciousAppInfo,
1013
type TalsecConfig,
1114
} from './definitions';
1215
import { getThreatCount, itemsHaveType } from './utils';
16+
import { decode } from 'base-64';
1317

1418
const { FreeraspReactNative } = NativeModules;
1519

@@ -31,9 +35,10 @@ const getThreatIdentifiers = async (): Promise<number[]> => {
3135
return identifiers;
3236
};
3337

34-
const getThreatChannelData = async (): Promise<[string, string]> => {
38+
const getThreatChannelData = async (): Promise<[string, string, string]> => {
39+
const dataLength = Platform.OS === 'ios' ? 2 : 3;
3540
let data = await FreeraspReactNative.getThreatChannelData();
36-
if (data.length !== 2 || !itemsHaveType(data, 'string')) {
41+
if (data.length !== dataLength || !itemsHaveType(data, 'string')) {
3742
onInvalidCallback();
3843
}
3944
return data;
@@ -48,10 +53,25 @@ const prepareMapping = async (): Promise<void> => {
4853
});
4954
};
5055

56+
// parses base64-encoded malware data to SuspiciousAppInfo[]
57+
const parseMalwareData = (data: string[]): SuspiciousAppInfo[] => {
58+
const result: SuspiciousAppInfo[] = [];
59+
data.forEach((entry) => {
60+
result.push(toSuspiciousAppInfo(entry));
61+
});
62+
return result;
63+
};
64+
65+
const toSuspiciousAppInfo = (base64Value: string): SuspiciousAppInfo => {
66+
const data = JSON.parse(decode(base64Value));
67+
const packageInfo = data.packageInfo as PackageInfo;
68+
return { packageInfo, reason: data.reason } as SuspiciousAppInfo;
69+
};
70+
5171
export const setThreatListeners = async <T extends NativeEventEmitterActions>(
5272
config: T & Record<Exclude<keyof T, keyof NativeEventEmitterActions>, []>
5373
) => {
54-
const [channel, key] = await getThreatChannelData();
74+
const [channel, key, malwareKey] = await getThreatChannelData();
5575
await prepareMapping();
5676

5777
eventsListener = eventEmitter.addListener(channel, (event) => {
@@ -98,6 +118,9 @@ export const setThreatListeners = async <T extends NativeEventEmitterActions>(
98118
case Threat.SystemVPN.value:
99119
config.systemVPN?.();
100120
break;
121+
case Threat.Malware.value:
122+
config.malware?.(parseMalwareData(event[malwareKey]));
123+
break;
101124
default:
102125
onInvalidCallback();
103126
break;
@@ -138,4 +161,12 @@ export const useFreeRasp = <T extends NativeEventEmitterActions>(
138161
}, []);
139162
};
140163

164+
export const addToWhitelist = async (packageName: string): Promise<boolean> => {
165+
if (Platform.OS === 'ios') {
166+
return Promise.reject('Malware detection not available on iOS');
167+
}
168+
return FreeraspReactNative.addToWhitelist(packageName);
169+
};
170+
171+
export * from './definitions';
141172
export default FreeraspReactNative;

yarn.lock

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2606,6 +2606,11 @@
26062606
dependencies:
26072607
"@babel/types" "^7.20.7"
26082608

2609+
"@types/base-64@^1.0.2":
2610+
version "1.0.2"
2611+
resolved "https://registry.yarnpkg.com/@types/base-64/-/base-64-1.0.2.tgz#f7bc80d242306f20c57f076d79d1efe2d31032ca"
2612+
integrity sha512-uPgKMmM9fmn7I+Zi6YBqctOye4SlJsHKcisjHIMWpb2YKZRc36GpKyNuQ03JcT+oNXg1m7Uv4wU94EVltn8/cw==
2613+
26092614
"@types/graceful-fs@^4.1.3":
26102615
version "4.1.9"
26112616
resolved "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz"
@@ -3513,6 +3518,11 @@ balanced-match@^1.0.0:
35133518
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
35143519
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
35153520

3521+
base-64@^1.0.0:
3522+
version "1.0.0"
3523+
resolved "https://registry.yarnpkg.com/base-64/-/base-64-1.0.0.tgz#09d0f2084e32a3fd08c2475b973788eee6ae8f4a"
3524+
integrity sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==
3525+
35163526
base64-js@^1.1.2, base64-js@^1.2.3, base64-js@^1.3.1, base64-js@^1.5.1:
35173527
version "1.5.1"
35183528
resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz"

0 commit comments

Comments
 (0)