react-native-device-integrity 0.1.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 (54) hide show
  1. package/DeviceIntegrity.podspec +21 -0
  2. package/LICENSE +20 -0
  3. package/README.md +286 -0
  4. package/android/build.gradle +55 -0
  5. package/android/src/main/AndroidManifest.xml +20 -0
  6. package/android/src/main/java/com/deviceintegrity/DeviceIntegrityModule.kt +48 -0
  7. package/android/src/main/java/com/deviceintegrity/DeviceIntegrityPackage.kt +31 -0
  8. package/android/src/main/java/com/deviceintegrity/IntegrityChecks.kt +454 -0
  9. package/app.plugin.js +1 -0
  10. package/ios/DIIntegrityChecks.h +15 -0
  11. package/ios/DIIntegrityChecks.m +395 -0
  12. package/ios/DeviceIntegrity.h +5 -0
  13. package/ios/DeviceIntegrity.mm +29 -0
  14. package/ios/PrivacyInfo.xcprivacy +14 -0
  15. package/lib/module/NativeDeviceIntegrity.js +5 -0
  16. package/lib/module/NativeDeviceIntegrity.js.map +1 -0
  17. package/lib/module/checkIntegrity.js +15 -0
  18. package/lib/module/checkIntegrity.js.map +1 -0
  19. package/lib/module/checkIntegrity.native.js +67 -0
  20. package/lib/module/checkIntegrity.native.js.map +1 -0
  21. package/lib/module/index.js +5 -0
  22. package/lib/module/index.js.map +1 -0
  23. package/lib/module/package.json +1 -0
  24. package/lib/module/resolveStatus.js +76 -0
  25. package/lib/module/resolveStatus.js.map +1 -0
  26. package/lib/module/types.js +4 -0
  27. package/lib/module/types.js.map +1 -0
  28. package/lib/module/useDeviceIntegrity.js +62 -0
  29. package/lib/module/useDeviceIntegrity.js.map +1 -0
  30. package/lib/typescript/package.json +1 -0
  31. package/lib/typescript/src/NativeDeviceIntegrity.d.ts +17 -0
  32. package/lib/typescript/src/NativeDeviceIntegrity.d.ts.map +1 -0
  33. package/lib/typescript/src/checkIntegrity.d.ts +6 -0
  34. package/lib/typescript/src/checkIntegrity.d.ts.map +1 -0
  35. package/lib/typescript/src/checkIntegrity.native.d.ts +3 -0
  36. package/lib/typescript/src/checkIntegrity.native.d.ts.map +1 -0
  37. package/lib/typescript/src/index.d.ts +4 -0
  38. package/lib/typescript/src/index.d.ts.map +1 -0
  39. package/lib/typescript/src/resolveStatus.d.ts +8 -0
  40. package/lib/typescript/src/resolveStatus.d.ts.map +1 -0
  41. package/lib/typescript/src/types.d.ts +23 -0
  42. package/lib/typescript/src/types.d.ts.map +1 -0
  43. package/lib/typescript/src/useDeviceIntegrity.d.ts +10 -0
  44. package/lib/typescript/src/useDeviceIntegrity.d.ts.map +1 -0
  45. package/package.json +210 -0
  46. package/plugin/build/index.d.ts +19 -0
  47. package/plugin/build/index.js +49 -0
  48. package/src/NativeDeviceIntegrity.ts +19 -0
  49. package/src/checkIntegrity.native.ts +88 -0
  50. package/src/checkIntegrity.ts +16 -0
  51. package/src/index.tsx +10 -0
  52. package/src/resolveStatus.ts +125 -0
  53. package/src/types.ts +41 -0
  54. package/src/useDeviceIntegrity.ts +92 -0
@@ -0,0 +1,395 @@
1
+ // Check set informed by IOSSecuritySuite and the OWASP MASTG; independent implementation.
2
+
3
+ #import "DIIntegrityChecks.h"
4
+
5
+ #import <UIKit/UIKit.h>
6
+ #import <mach-o/dyld.h>
7
+ #import <sys/sysctl.h>
8
+ #import <unistd.h>
9
+
10
+ @interface DIIntegrityChecks ()
11
+ + (void)addSignalId:(NSString *)signalId
12
+ category:(NSString *)category
13
+ description:(NSString *)description
14
+ signals:(NSMutableArray<NSDictionary *> *)signals
15
+ seenIds:(NSMutableSet<NSString *> *)seenIds;
16
+ + (BOOL)pathExists:(NSString *)path;
17
+ + (BOOL)hasJailbreakFiles;
18
+ + (BOOL)hasJailbreakURLSchemes;
19
+ + (BOOL)hasJailbreakSymlinks;
20
+ + (BOOL)isSystemWritable;
21
+ + (BOOL)hasHookingLibraries;
22
+ + (BOOL)hasDyldInsertLibraries;
23
+ + (BOOL)isDebuggerAttached;
24
+ @end
25
+
26
+ @implementation DIIntegrityChecks
27
+
28
+ + (void)addSignalId:(NSString *)signalId
29
+ category:(NSString *)category
30
+ description:(NSString *)description
31
+ signals:(NSMutableArray<NSDictionary *> *)signals
32
+ seenIds:(NSMutableSet<NSString *> *)seenIds
33
+ {
34
+ if ([seenIds containsObject:signalId]) {
35
+ return;
36
+ }
37
+ [seenIds addObject:signalId];
38
+ [signals addObject:@{
39
+ @"id" : signalId,
40
+ @"category" : category,
41
+ @"description" : description,
42
+ }];
43
+ }
44
+
45
+ + (NSDictionary *)buildReportWithSignals:(NSArray *)signals completed:(BOOL)completed
46
+ {
47
+ NSMutableDictionary *report = [@{
48
+ @"completed" : @(completed),
49
+ @"signals" : signals,
50
+ } mutableCopy];
51
+ if (!completed) {
52
+ report[@"reason"] = @"incomplete";
53
+ }
54
+ return [report copy];
55
+ }
56
+
57
+ + (void)runWithCompletion:(void (^)(NSDictionary *report))completion
58
+ {
59
+ dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
60
+ NSMutableArray<NSDictionary *> *signals = [NSMutableArray array];
61
+ NSMutableSet<NSString *> *seenIds = [NSMutableSet set];
62
+ __block BOOL completed = YES;
63
+
64
+ #if TARGET_OS_SIMULATOR
65
+ [self addSignalId:@"simulator"
66
+ category:@"emulator"
67
+ description:@"Running on the iOS Simulator"
68
+ signals:signals
69
+ seenIds:seenIds];
70
+ #endif
71
+
72
+ // --- hooking_libraries (always) ---
73
+ @try {
74
+ if ([self hasHookingLibraries]) {
75
+ [self addSignalId:@"hooking_libraries"
76
+ category:@"hooking"
77
+ description:@"Suspicious dynamic libraries are loaded"
78
+ signals:signals
79
+ seenIds:seenIds];
80
+ }
81
+ } @catch (__unused NSException *exception) {
82
+ completed = NO;
83
+ }
84
+
85
+ // --- debugger_attached (always) ---
86
+ @try {
87
+ if ([self isDebuggerAttached]) {
88
+ [self addSignalId:@"debugger_attached"
89
+ category:@"debugger"
90
+ description:@"A debugger is attached to the process"
91
+ signals:signals
92
+ seenIds:seenIds];
93
+ }
94
+ } @catch (__unused NSException *exception) {
95
+ completed = NO;
96
+ }
97
+
98
+ #if TARGET_OS_SIMULATOR
99
+ // Simulator: host Mac filesystem and Xcode-injected DYLD_INSERT_LIBRARIES
100
+ // make jailbreak / dyld-insert checks meaningless — skip by design.
101
+ // Skipped-by-design is not incomplete.
102
+ completion([self buildReportWithSignals:[signals copy] completed:completed]);
103
+ #else
104
+ @try {
105
+ if ([self hasJailbreakFiles]) {
106
+ [self addSignalId:@"jailbreak_files"
107
+ category:@"jailbreak"
108
+ description:@"Unexpected system paths associated with jailbreaks were found"
109
+ signals:signals
110
+ seenIds:seenIds];
111
+ }
112
+ } @catch (__unused NSException *exception) {
113
+ completed = NO;
114
+ }
115
+
116
+ @try {
117
+ if ([self hasJailbreakSymlinks]) {
118
+ [self addSignalId:@"jailbreak_symlinks"
119
+ category:@"jailbreak"
120
+ description:@"Unexpected symbolic links were found in system locations"
121
+ signals:signals
122
+ seenIds:seenIds];
123
+ }
124
+ } @catch (__unused NSException *exception) {
125
+ completed = NO;
126
+ }
127
+
128
+ @try {
129
+ if ([self isSystemWritable]) {
130
+ [self addSignalId:@"jailbreak_writable_system"
131
+ category:@"jailbreak"
132
+ description:@"A normally read-only system location is writable"
133
+ signals:signals
134
+ seenIds:seenIds];
135
+ }
136
+ } @catch (__unused NSException *exception) {
137
+ completed = NO;
138
+ }
139
+
140
+ @try {
141
+ if ([self hasDyldInsertLibraries]) {
142
+ [self addSignalId:@"hooking_dyld_insert"
143
+ category:@"hooking"
144
+ description:@"DYLD_INSERT_LIBRARIES is set in the process environment"
145
+ signals:signals
146
+ seenIds:seenIds];
147
+ }
148
+ } @catch (__unused NSException *exception) {
149
+ completed = NO;
150
+ }
151
+
152
+ // canOpenURL: must run on the main thread.
153
+ // These schemes need LSApplicationQueriesSchemes (added by the Expo config
154
+ // plugin in Phase 3 / documented for bare apps); without it canOpenURL
155
+ // just returns NO.
156
+ dispatch_async(dispatch_get_main_queue(), ^{
157
+ @try {
158
+ if ([self hasJailbreakURLSchemes]) {
159
+ [self addSignalId:@"jailbreak_url_schemes"
160
+ category:@"jailbreak"
161
+ description:@"Jailbreak-related URL schemes are registered"
162
+ signals:signals
163
+ seenIds:seenIds];
164
+ }
165
+ } @catch (__unused NSException *exception) {
166
+ completed = NO;
167
+ }
168
+
169
+ completion([self buildReportWithSignals:[signals copy] completed:completed]);
170
+ });
171
+ #endif
172
+ });
173
+ }
174
+
175
+ #pragma mark - Individual checks
176
+
177
+ + (BOOL)pathExists:(NSString *)path
178
+ {
179
+ if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
180
+ return YES;
181
+ }
182
+ const char *cPath = [path fileSystemRepresentation];
183
+ if (cPath == NULL) {
184
+ return NO;
185
+ }
186
+ return access(cPath, F_OK) == 0;
187
+ }
188
+
189
+ + (BOOL)hasJailbreakFiles
190
+ {
191
+ static NSArray<NSString *> *paths = nil;
192
+ static dispatch_once_t onceToken;
193
+ dispatch_once(&onceToken, ^{
194
+ paths = @[
195
+ @"/Applications/Cydia.app",
196
+ @"/Applications/Sileo.app",
197
+ @"/Applications/Zebra.app",
198
+ @"/Applications/Filza.app",
199
+ @"/Applications/Installer.app",
200
+ @"/Applications/Undecimus.app",
201
+ @"/Applications/blackra1n.app",
202
+ @"/Applications/FakeCarrier.app",
203
+ @"/Applications/Icy.app",
204
+ @"/Applications/IntelliScreen.app",
205
+ @"/Applications/MxTube.app",
206
+ @"/Applications/RockApp.app",
207
+ @"/Applications/SBSettings.app",
208
+ @"/Applications/WinterBoard.app",
209
+ @"/Library/MobileSubstrate/MobileSubstrate.dylib",
210
+ @"/Library/MobileSubstrate/DynamicLibraries",
211
+ @"/usr/lib/libsubstrate.dylib",
212
+ @"/usr/lib/substitute-inserter.dylib",
213
+ @"/usr/lib/libhooker.dylib",
214
+ @"/usr/lib/TweakInject",
215
+ @"/usr/lib/libellekit.dylib",
216
+ @"/usr/lib/ellekit/libinjector.dylib",
217
+ @"/private/var/lib/apt",
218
+ @"/private/var/lib/apt/",
219
+ @"/private/var/lib/cydia",
220
+ @"/private/var/mobile/Library/SBSettings/Themes",
221
+ @"/private/var/stash",
222
+ @"/private/var/tmp/cydia.log",
223
+ @"/private/var/db/stash",
224
+ @"/usr/sbin/sshd",
225
+ @"/usr/bin/ssh",
226
+ @"/usr/bin/sshd",
227
+ @"/usr/libexec/cydia",
228
+ @"/usr/libexec/sftp-server",
229
+ @"/usr/libexec/ssh-keysign",
230
+ @"/bin/bash",
231
+ @"/etc/apt",
232
+ @"/etc/ssh/sshd_config",
233
+ @"/var/jb",
234
+ @"/var/binpack",
235
+ @"/var/checkra1n.dmg",
236
+ @"/.bootstrapped",
237
+ @"/.installed_unc0ver",
238
+ @"/.cydia_no_stash",
239
+ @"/jb/amfid_payload.dylib",
240
+ @"/jb/jailbreakd.plist",
241
+ @"/jb/libjailbreak.dylib",
242
+ @"/chimera/jailbreakd.plist",
243
+ @"/odyssey/jailbreakd.plist",
244
+ ];
245
+ });
246
+
247
+ for (NSString *path in paths) {
248
+ if ([self pathExists:path]) {
249
+ return YES;
250
+ }
251
+ }
252
+ return NO;
253
+ }
254
+
255
+ + (BOOL)hasJailbreakURLSchemes
256
+ {
257
+ // Requires LSApplicationQueriesSchemes entries; without them canOpenURL
258
+ // returns NO even when the target app is installed.
259
+ static NSArray<NSString *> *schemes = nil;
260
+ static dispatch_once_t onceToken;
261
+ dispatch_once(&onceToken, ^{
262
+ schemes = @[
263
+ @"cydia://",
264
+ @"sileo://",
265
+ @"zbra://",
266
+ @"filza://",
267
+ @"undecimus://",
268
+ @"activator://",
269
+ ];
270
+ });
271
+
272
+ UIApplication *app = [UIApplication sharedApplication];
273
+ for (NSString *scheme in schemes) {
274
+ NSURL *url = [NSURL URLWithString:scheme];
275
+ if (url != nil && [app canOpenURL:url]) {
276
+ return YES;
277
+ }
278
+ }
279
+ return NO;
280
+ }
281
+
282
+ + (BOOL)hasJailbreakSymlinks
283
+ {
284
+ static NSArray<NSString *> *paths = nil;
285
+ static dispatch_once_t onceToken;
286
+ dispatch_once(&onceToken, ^{
287
+ paths = @[
288
+ @"/Applications",
289
+ @"/Library/Ringtones",
290
+ @"/Library/Wallpaper",
291
+ @"/usr/arm-apple-darwin9",
292
+ @"/usr/include",
293
+ @"/usr/libexec",
294
+ @"/usr/share",
295
+ ];
296
+ });
297
+
298
+ NSFileManager *fm = [NSFileManager defaultManager];
299
+ for (NSString *path in paths) {
300
+ NSError *error = nil;
301
+ NSString *destination =
302
+ [fm destinationOfSymbolicLinkAtPath:path error:&error];
303
+ if (destination != nil) {
304
+ return YES;
305
+ }
306
+ }
307
+ return NO;
308
+ }
309
+
310
+ + (BOOL)isSystemWritable
311
+ {
312
+ NSString *probeName =
313
+ [NSString stringWithFormat:@"di_integrity_%@", [[NSUUID UUID] UUIDString]];
314
+ NSString *probePath = [@"/private/" stringByAppendingPathComponent:probeName];
315
+ const char *cPath = [probePath fileSystemRepresentation];
316
+ if (cPath == NULL) {
317
+ return NO;
318
+ }
319
+
320
+ FILE *file = fopen(cPath, "w");
321
+ if (file == NULL) {
322
+ return NO;
323
+ }
324
+ fputs("x", file);
325
+ fclose(file);
326
+ unlink(cPath);
327
+ return YES;
328
+ }
329
+
330
+ + (BOOL)hasHookingLibraries
331
+ {
332
+ static NSArray<NSString *> *needles = nil;
333
+ static dispatch_once_t onceToken;
334
+ dispatch_once(&onceToken, ^{
335
+ needles = @[
336
+ @"frida",
337
+ @"fridagadget",
338
+ @"cynject",
339
+ @"libcycript",
340
+ @"mobilesubstrate",
341
+ @"substrateloader",
342
+ @"substrateinserter",
343
+ @"substitute",
344
+ @"libhooker",
345
+ @"ellekit",
346
+ @"tweakinject",
347
+ @"sslkillswitch",
348
+ @"revealserver",
349
+ @"systemhook",
350
+ ];
351
+ });
352
+
353
+ uint32_t count = _dyld_image_count();
354
+ for (uint32_t i = 0; i < count; i++) {
355
+ const char *imageName = _dyld_get_image_name(i);
356
+ if (imageName == NULL) {
357
+ continue;
358
+ }
359
+ NSString *name =
360
+ [[NSString stringWithUTF8String:imageName] lowercaseString];
361
+ if (name == nil) {
362
+ continue;
363
+ }
364
+ for (NSString *needle in needles) {
365
+ if ([name rangeOfString:needle].location != NSNotFound) {
366
+ return YES;
367
+ }
368
+ }
369
+ }
370
+ return NO;
371
+ }
372
+
373
+ + (BOOL)hasDyldInsertLibraries
374
+ {
375
+ const char *value = getenv("DYLD_INSERT_LIBRARIES");
376
+ if (value == NULL) {
377
+ return NO;
378
+ }
379
+ return value[0] != '\0';
380
+ }
381
+
382
+ + (BOOL)isDebuggerAttached
383
+ {
384
+ int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()};
385
+ struct kinfo_proc info;
386
+ memset(&info, 0, sizeof(info));
387
+ size_t size = sizeof(info);
388
+
389
+ if (sysctl(mib, 4, &info, &size, NULL, 0) != 0) {
390
+ return NO;
391
+ }
392
+ return (info.kp_proc.p_flag & P_TRACED) != 0;
393
+ }
394
+
395
+ @end
@@ -0,0 +1,5 @@
1
+ #import <DeviceIntegritySpec/DeviceIntegritySpec.h>
2
+
3
+ @interface DeviceIntegrity : NSObject <NativeDeviceIntegritySpec>
4
+
5
+ @end
@@ -0,0 +1,29 @@
1
+ #import "DeviceIntegrity.h"
2
+ #import "DIIntegrityChecks.h"
3
+
4
+ @implementation DeviceIntegrity
5
+
6
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
7
+ (const facebook::react::ObjCTurboModule::InitParams &)params
8
+ {
9
+ return std::make_shared<facebook::react::NativeDeviceIntegritySpecJSI>(params);
10
+ }
11
+
12
+ + (NSString *)moduleName
13
+ {
14
+ return @"DeviceIntegrity";
15
+ }
16
+
17
+ - (void)checkIntegrity:(RCTPromiseResolveBlock)resolve
18
+ reject:(RCTPromiseRejectBlock)reject
19
+ {
20
+ @try {
21
+ [DIIntegrityChecks runWithCompletion:^(NSDictionary *report) {
22
+ resolve(report);
23
+ }];
24
+ } @catch (NSException *exception) {
25
+ reject(@"E_INTEGRITY", exception.reason ?: @"Unexpected integrity check failure", nil);
26
+ }
27
+ }
28
+
29
+ @end
@@ -0,0 +1,14 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>NSPrivacyTracking</key>
6
+ <false/>
7
+ <key>NSPrivacyTrackingDomains</key>
8
+ <array/>
9
+ <key>NSPrivacyCollectedDataTypes</key>
10
+ <array/>
11
+ <key>NSPrivacyAccessedAPITypes</key>
12
+ <array/>
13
+ </dict>
14
+ </plist>
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ import { TurboModuleRegistry } from 'react-native';
4
+ export default TurboModuleRegistry.get('DeviceIntegrity');
5
+ //# sourceMappingURL=NativeDeviceIntegrity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["TurboModuleRegistry","get"],"sourceRoot":"../../src","sources":["NativeDeviceIntegrity.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;AAkBpE,eAAeA,mBAAmB,CAACC,GAAG,CAAO,iBAAiB,CAAC","ignoreList":[]}
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ import { Platform } from 'react-native';
4
+ /**
5
+ * Web / unsupported-platform entry. Must not import the native TurboModule.
6
+ */
7
+ export async function checkIntegrity(_options) {
8
+ return {
9
+ status: 'unknown',
10
+ signals: [],
11
+ platform: Platform.OS,
12
+ reason: 'unsupported_platform'
13
+ };
14
+ }
15
+ //# sourceMappingURL=checkIntegrity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Platform","checkIntegrity","_options","status","signals","platform","OS","reason"],"sourceRoot":"../../src","sources":["checkIntegrity.ts"],"mappings":";;AAAA,SAASA,QAAQ,QAAQ,cAAc;AAGvC;AACA;AACA;AACA,OAAO,eAAeC,cAAcA,CAClCC,QAAgC,EACN;EAC1B,OAAO;IACLC,MAAM,EAAE,SAAS;IACjBC,OAAO,EAAE,EAAE;IACXC,QAAQ,EAAEL,QAAQ,CAACM,EAAE;IACrBC,MAAM,EAAE;EACV,CAAC;AACH","ignoreList":[]}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+
3
+ import { Platform } from 'react-native';
4
+ import NativeDeviceIntegrity from "./NativeDeviceIntegrity.js";
5
+ import { resolveStatus } from "./resolveStatus.js";
6
+ const DEFAULT_TIMEOUT_MS = 10_000;
7
+ class IntegrityTimeoutError extends Error {
8
+ constructor() {
9
+ super('Device integrity check timed out');
10
+ this.name = 'IntegrityTimeoutError';
11
+ }
12
+ }
13
+ function withTimeout(promise, timeoutMs) {
14
+ return new Promise((resolve, reject) => {
15
+ const timer = setTimeout(() => {
16
+ reject(new IntegrityTimeoutError());
17
+ }, timeoutMs);
18
+ promise.then(value => {
19
+ clearTimeout(timer);
20
+ resolve(value);
21
+ }, error => {
22
+ clearTimeout(timer);
23
+ reject(error);
24
+ });
25
+ });
26
+ }
27
+ export async function checkIntegrity(options = {}) {
28
+ if (Platform.OS !== 'ios' && Platform.OS !== 'android') {
29
+ return {
30
+ status: 'unknown',
31
+ signals: [],
32
+ platform: Platform.OS,
33
+ reason: 'unsupported_platform'
34
+ };
35
+ }
36
+ if (NativeDeviceIntegrity == null) {
37
+ return {
38
+ status: 'unknown',
39
+ signals: [],
40
+ platform: Platform.OS,
41
+ reason: 'native_module_unavailable'
42
+ };
43
+ }
44
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
45
+ try {
46
+ const report = await withTimeout(NativeDeviceIntegrity.checkIntegrity(), timeoutMs);
47
+ return resolveStatus(report, options, Platform.OS);
48
+ } catch (error) {
49
+ if (error instanceof IntegrityTimeoutError) {
50
+ return {
51
+ status: 'unknown',
52
+ signals: [],
53
+ platform: Platform.OS,
54
+ reason: 'timeout'
55
+ };
56
+ }
57
+ const message = error instanceof Error ? error.message : typeof error === 'string' ? error : 'Native integrity check failed';
58
+ return {
59
+ status: 'unknown',
60
+ signals: [],
61
+ platform: Platform.OS,
62
+ reason: 'native_error',
63
+ error: message
64
+ };
65
+ }
66
+ }
67
+ //# sourceMappingURL=checkIntegrity.native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Platform","NativeDeviceIntegrity","resolveStatus","DEFAULT_TIMEOUT_MS","IntegrityTimeoutError","Error","constructor","name","withTimeout","promise","timeoutMs","Promise","resolve","reject","timer","setTimeout","then","value","clearTimeout","error","checkIntegrity","options","OS","status","signals","platform","reason","report","message"],"sourceRoot":"../../src","sources":["checkIntegrity.native.ts"],"mappings":";;AAAA,SAASA,QAAQ,QAAQ,cAAc;AACvC,OAAOC,qBAAqB,MAAM,4BAAyB;AAC3D,SAASC,aAAa,QAAQ,oBAAiB;AAG/C,MAAMC,kBAAkB,GAAG,MAAM;AAEjC,MAAMC,qBAAqB,SAASC,KAAK,CAAC;EACxCC,WAAWA,CAAA,EAAG;IACZ,KAAK,CAAC,kCAAkC,CAAC;IACzC,IAAI,CAACC,IAAI,GAAG,uBAAuB;EACrC;AACF;AAEA,SAASC,WAAWA,CAAIC,OAAmB,EAAEC,SAAiB,EAAc;EAC1E,OAAO,IAAIC,OAAO,CAAI,CAACC,OAAO,EAAEC,MAAM,KAAK;IACzC,MAAMC,KAAK,GAAGC,UAAU,CAAC,MAAM;MAC7BF,MAAM,CAAC,IAAIT,qBAAqB,CAAC,CAAC,CAAC;IACrC,CAAC,EAAEM,SAAS,CAAC;IAEbD,OAAO,CAACO,IAAI,CACTC,KAAK,IAAK;MACTC,YAAY,CAACJ,KAAK,CAAC;MACnBF,OAAO,CAACK,KAAK,CAAC;IAChB,CAAC,EACAE,KAAc,IAAK;MAClBD,YAAY,CAACJ,KAAK,CAAC;MACnBD,MAAM,CAACM,KAAK,CAAC;IACf,CACF,CAAC;EACH,CAAC,CAAC;AACJ;AAEA,OAAO,eAAeC,cAAcA,CAClCC,OAA8B,GAAG,CAAC,CAAC,EACT;EAC1B,IAAIrB,QAAQ,CAACsB,EAAE,KAAK,KAAK,IAAItB,QAAQ,CAACsB,EAAE,KAAK,SAAS,EAAE;IACtD,OAAO;MACLC,MAAM,EAAE,SAAS;MACjBC,OAAO,EAAE,EAAE;MACXC,QAAQ,EAAEzB,QAAQ,CAACsB,EAAE;MACrBI,MAAM,EAAE;IACV,CAAC;EACH;EAEA,IAAIzB,qBAAqB,IAAI,IAAI,EAAE;IACjC,OAAO;MACLsB,MAAM,EAAE,SAAS;MACjBC,OAAO,EAAE,EAAE;MACXC,QAAQ,EAAEzB,QAAQ,CAACsB,EAAE;MACrBI,MAAM,EAAE;IACV,CAAC;EACH;EAEA,MAAMhB,SAAS,GAAGW,OAAO,CAACX,SAAS,IAAIP,kBAAkB;EAEzD,IAAI;IACF,MAAMwB,MAAM,GAAG,MAAMnB,WAAW,CAC9BP,qBAAqB,CAACmB,cAAc,CAAC,CAAC,EACtCV,SACF,CAAC;IACD,OAAOR,aAAa,CAACyB,MAAM,EAAEN,OAAO,EAAErB,QAAQ,CAACsB,EAAE,CAAC;EACpD,CAAC,CAAC,OAAOH,KAAK,EAAE;IACd,IAAIA,KAAK,YAAYf,qBAAqB,EAAE;MAC1C,OAAO;QACLmB,MAAM,EAAE,SAAS;QACjBC,OAAO,EAAE,EAAE;QACXC,QAAQ,EAAEzB,QAAQ,CAACsB,EAAE;QACrBI,MAAM,EAAE;MACV,CAAC;IACH;IAEA,MAAME,OAAO,GACXT,KAAK,YAAYd,KAAK,GAClBc,KAAK,CAACS,OAAO,GACb,OAAOT,KAAK,KAAK,QAAQ,GACvBA,KAAK,GACL,+BAA+B;IAEvC,OAAO;MACLI,MAAM,EAAE,SAAS;MACjBC,OAAO,EAAE,EAAE;MACXC,QAAQ,EAAEzB,QAAQ,CAACsB,EAAE;MACrBI,MAAM,EAAE,cAAc;MACtBP,KAAK,EAAES;IACT,CAAC;EACH;AACF","ignoreList":[]}
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ export { checkIntegrity } from './checkIntegrity';
4
+ export { useDeviceIntegrity } from "./useDeviceIntegrity.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["checkIntegrity","useDeviceIntegrity"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,cAAc,QAAQ,kBAAkB;AACjD,SAASC,kBAAkB,QAAQ,yBAAsB","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+
3
+ const SIGNAL_CATEGORIES = new Set(['jailbreak', 'root', 'hooking', 'debugger', 'emulator', 'tamper', 'environment']);
4
+ function coerceCategory(category) {
5
+ if (typeof category === 'string' && SIGNAL_CATEGORIES.has(category)) {
6
+ return category;
7
+ }
8
+ return 'environment';
9
+ }
10
+ function normalizeSignal(raw) {
11
+ if (raw === null || typeof raw !== 'object') {
12
+ return {
13
+ id: 'unknown_signal',
14
+ category: 'environment',
15
+ description: ''
16
+ };
17
+ }
18
+ const signal = raw;
19
+ const id = typeof signal.id === 'string' && signal.id.length > 0 ? signal.id : 'unknown_signal';
20
+ const description = typeof signal.description === 'string' ? signal.description : '';
21
+ return {
22
+ id,
23
+ category: coerceCategory(signal.category),
24
+ description
25
+ };
26
+ }
27
+ function malformed(platform, error) {
28
+ return {
29
+ status: 'unknown',
30
+ signals: [],
31
+ platform,
32
+ reason: 'native_error',
33
+ error
34
+ };
35
+ }
36
+
37
+ /**
38
+ * Maps a native integrity report + options to the public IntegrityResult.
39
+ * Compromise evidence wins over incomplete runs; incomplete/malformed never become 'clean'.
40
+ */
41
+ export function resolveStatus(report, options = {}, platform) {
42
+ if (report === null || typeof report !== 'object' || Array.isArray(report)) {
43
+ return malformed(platform, 'Malformed native integrity report');
44
+ }
45
+ const nativeReport = report;
46
+ if (!Array.isArray(nativeReport.signals)) {
47
+ return malformed(platform, 'Malformed native integrity report');
48
+ }
49
+ const signals = nativeReport.signals.map(normalizeSignal);
50
+ const completed = nativeReport.completed === true;
51
+ const treatEmulatorAsCompromised = options.treatEmulatorAsCompromised === true;
52
+ const hasNonEmulatorSignal = signals.some(signal => signal.category !== 'emulator');
53
+ const hasEmulatorSignal = signals.some(signal => signal.category === 'emulator');
54
+ if (hasNonEmulatorSignal || hasEmulatorSignal && treatEmulatorAsCompromised) {
55
+ return {
56
+ status: 'compromised',
57
+ signals,
58
+ platform
59
+ };
60
+ }
61
+ if (!completed) {
62
+ const reason = nativeReport.reason === 'not_implemented' ? 'not_implemented' : 'incomplete';
63
+ return {
64
+ status: 'unknown',
65
+ signals,
66
+ platform,
67
+ reason
68
+ };
69
+ }
70
+ return {
71
+ status: 'clean',
72
+ signals,
73
+ platform
74
+ };
75
+ }
76
+ //# sourceMappingURL=resolveStatus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["SIGNAL_CATEGORIES","Set","coerceCategory","category","has","normalizeSignal","raw","id","description","signal","length","malformed","platform","error","status","signals","reason","resolveStatus","report","options","Array","isArray","nativeReport","map","completed","treatEmulatorAsCompromised","hasNonEmulatorSignal","some","hasEmulatorSignal"],"sourceRoot":"../../src","sources":["resolveStatus.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"","ignoreList":[]}