@cap-kit/integrity 8.0.0-next.6

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 (59) hide show
  1. package/CapKitIntegrity.podspec +17 -0
  2. package/LICENSE +21 -0
  3. package/Package.swift +26 -0
  4. package/README.md +1104 -0
  5. package/android/build.gradle +104 -0
  6. package/android/src/main/AndroidManifest.xml +21 -0
  7. package/android/src/main/java/io/capkit/integrity/IntegrityCheckOptions.kt +37 -0
  8. package/android/src/main/java/io/capkit/integrity/IntegrityConfig.kt +59 -0
  9. package/android/src/main/java/io/capkit/integrity/IntegrityError.kt +40 -0
  10. package/android/src/main/java/io/capkit/integrity/IntegrityImpl.kt +319 -0
  11. package/android/src/main/java/io/capkit/integrity/IntegrityPlugin.kt +475 -0
  12. package/android/src/main/java/io/capkit/integrity/IntegrityReportBuilder.kt +130 -0
  13. package/android/src/main/java/io/capkit/integrity/IntegritySignalBuilder.kt +72 -0
  14. package/android/src/main/java/io/capkit/integrity/emulator/IntegrityEmulatorChecks.kt +38 -0
  15. package/android/src/main/java/io/capkit/integrity/filesystem/IntegrityFilesystemChecks.kt +51 -0
  16. package/android/src/main/java/io/capkit/integrity/hook/IntegrityHookChecks.kt +61 -0
  17. package/android/src/main/java/io/capkit/integrity/remote/IntegrityRemoteAttestor.kt +49 -0
  18. package/android/src/main/java/io/capkit/integrity/root/IntegrityRootDetector.kt +136 -0
  19. package/android/src/main/java/io/capkit/integrity/runtime/IntegrityRuntimeChecks.kt +87 -0
  20. package/android/src/main/java/io/capkit/integrity/ui/IntegrityBlockActivity.kt +173 -0
  21. package/android/src/main/java/io/capkit/integrity/ui/IntegrityUISignals.kt +57 -0
  22. package/android/src/main/java/io/capkit/integrity/utils/IntegrityLogger.kt +85 -0
  23. package/android/src/main/java/io/capkit/integrity/utils/IntegrityUtils.kt +105 -0
  24. package/android/src/main/res/.gitkeep +0 -0
  25. package/android/src/main/res/values/styles.xml +5 -0
  26. package/dist/docs.json +598 -0
  27. package/dist/esm/definitions.d.ts +554 -0
  28. package/dist/esm/definitions.js +56 -0
  29. package/dist/esm/definitions.js.map +1 -0
  30. package/dist/esm/index.d.ts +15 -0
  31. package/dist/esm/index.js +16 -0
  32. package/dist/esm/index.js.map +1 -0
  33. package/dist/esm/web.d.ts +32 -0
  34. package/dist/esm/web.js +51 -0
  35. package/dist/esm/web.js.map +1 -0
  36. package/dist/plugin.cjs.js +130 -0
  37. package/dist/plugin.cjs.js.map +1 -0
  38. package/dist/plugin.js +133 -0
  39. package/dist/plugin.js.map +1 -0
  40. package/ios/Sources/IntegrityPlugin/IntegrityCheckOptions.swift +41 -0
  41. package/ios/Sources/IntegrityPlugin/IntegrityConfig.swift +135 -0
  42. package/ios/Sources/IntegrityPlugin/IntegrityEntitlementChecks.swift +58 -0
  43. package/ios/Sources/IntegrityPlugin/IntegrityError.swift +49 -0
  44. package/ios/Sources/IntegrityPlugin/IntegrityImpl.swift +397 -0
  45. package/ios/Sources/IntegrityPlugin/IntegrityPlugin.swift +345 -0
  46. package/ios/Sources/IntegrityPlugin/IntegrityReportBuilder.swift +184 -0
  47. package/ios/Sources/IntegrityPlugin/Utils/IntegrityLogger.swift +69 -0
  48. package/ios/Sources/IntegrityPlugin/Utils/IntegrityUtils.swift +144 -0
  49. package/ios/Sources/IntegrityPlugin/Version.swift +16 -0
  50. package/ios/Sources/IntegrityPlugin/filesystem/IntegrityFilesystemChecks.swift +86 -0
  51. package/ios/Sources/IntegrityPlugin/hook/IntegrityHookChecks.swift +85 -0
  52. package/ios/Sources/IntegrityPlugin/jailbreak/IntegrityJailbreakDetector.swift +74 -0
  53. package/ios/Sources/IntegrityPlugin/jailbreak/IntegrityJailbreakUrlSchemeDetector.swift +42 -0
  54. package/ios/Sources/IntegrityPlugin/remote/IntegrityRemoteAttestor.swift +40 -0
  55. package/ios/Sources/IntegrityPlugin/runtime/IntegrityRuntimeChecks.swift +63 -0
  56. package/ios/Sources/IntegrityPlugin/simulator/IntegritySimulatorChecks.swift +20 -0
  57. package/ios/Sources/IntegrityPlugin/ui/IntegrityBlockViewController.swift +143 -0
  58. package/ios/Tests/IntegrityPluginTests/IntegrityPluginTests.swift +10 -0
  59. package/package.json +106 -0
package/README.md ADDED
@@ -0,0 +1,1104 @@
1
+ <p align="center">
2
+ <img
3
+ src="https://raw.githubusercontent.com/cap-kit/capacitor-plugins/main/assets/logo.png"
4
+ alt="CapKit Logo"
5
+ width="128"
6
+ />
7
+ </p>
8
+
9
+ <h3 align="center">Integrity</h3>
10
+
11
+ <p align="center">
12
+ <strong>
13
+ <code>@cap-kit/integrity</code>
14
+ </strong>
15
+ </p>
16
+
17
+ <p align="center">
18
+ Runtime integrity and environment signal detection for Capacitor applications.<br>
19
+ Provides <strong>observational signals</strong> about the execution environment,
20
+ such as rooting, jailbreaking, emulators, instrumentation, and basic tampering
21
+ indicators on <strong>Android</strong> and <strong>iOS</strong>.<br><br>
22
+ Designed for <strong>Capacitor v8</strong>, with a stable, platform-agnostic
23
+ JavaScript API and first-class support for
24
+ <strong>Swift Package Manager</strong> and modern Android toolchains.
25
+ </p>
26
+
27
+ <p align="center">
28
+ <a href="https://www.npmjs.com/package/@cap-kit/integrity">
29
+ <img src="https://img.shields.io/npm/v/@cap-kit/integrity?color=blue&label=npm&logo=npm&style=flat-square" alt="npm version">
30
+ </a>
31
+ <a href="https://github.com/cap-kit/capacitor-plugins/actions">
32
+ <img src="https://img.shields.io/github/actions/workflow/status/cap-kit/capacitor-plugins/ci.yml?branch=main&label=CI&logo=github&style=flat-square" alt="CI Status" />
33
+ </a>
34
+ <a href="https://capacitorjs.com/">
35
+ <img src="https://img.shields.io/badge/Capacitor-Plugin-blue?logo=capacitor&style=flat-square" alt="Capacitor Plugin">
36
+ </a>
37
+ <a href="https://www.npmjs.com/package/@cap-kit/integrity">
38
+ <img src="https://img.shields.io/npm/dm/@cap-kit/integrity?style=flat-square" alt="Downloads" />
39
+ </a>
40
+ <a href="./LICENSE">
41
+ <img src="https://img.shields.io/npm/l/@cap-kit/integrity?style=flat-square&logo=open-source-initiative&logoColor=white&color=green" alt="License" />
42
+ </a>
43
+ <img src="https://img.shields.io/maintenance/yes/2026?style=flat-square" alt="Maintained" />
44
+ </p>
45
+
46
+ <br />
47
+
48
+ ---
49
+
50
+ ## Overview
51
+
52
+ `@cap-kit/integrity` provides **runtime integrity and environment signals**
53
+ for Capacitor applications on **Android** and **iOS**.
54
+
55
+ The plugin performs **best-effort detection** of conditions such as:
56
+
57
+ - Rooted / jailbroken devices
58
+ - Emulators and simulators
59
+ - Debug and instrumentation indicators
60
+ - Basic tampering and repackaging signals
61
+ - Frida and runtime hooking heuristics
62
+
63
+ The plugin **does NOT**:
64
+
65
+ - enforce security policies
66
+ - block or terminate the application
67
+ - present UI automatically
68
+ - guarantee protection against advanced attackers
69
+
70
+ All decisions are explicitly delegated to the **host application**.
71
+
72
+ ---
73
+
74
+ ## Versioning & Release Policy (IMPORTANT)
75
+
76
+ The `@cap-kit/integrity` plugin is currently under **active development** toward
77
+ a stable `v8.0.0` release.
78
+
79
+ All versions published as `v8.0.0-next.x` are considered:
80
+
81
+ They may include fully production-grade code,
82
+ but are published under the `next` tag to allow
83
+ controlled stabilization and incremental validation.
84
+
85
+ ---
86
+
87
+ ## Security Model (IMPORTANT)
88
+
89
+ This plugin follows an **observational security model**.
90
+
91
+ It reports **signals**, not decisions.
92
+
93
+ - Signals are heuristic observations
94
+ - Signals may produce false positives or false negatives
95
+ - The returned score is **provisional** and **non-normative**
96
+ - Consumers MUST combine signals with business logic
97
+
98
+ > ⚠️ This plugin is **NOT** a replacement for a full RASP or DRM solution.
99
+
100
+ ### Internal performance optimizations
101
+
102
+ To reduce repeated execution of expensive integrity checks,
103
+ the plugin applies a short-lived **negative cache** internally.
104
+
105
+ Key characteristics:
106
+
107
+ - Applies only to `standard` and `strict` levels
108
+ - Caches only **clean executions** (no detected signals)
109
+ - Time-to-live: **~30 seconds**
110
+ - Automatically invalidated as soon as any signal is detected
111
+ - Completely transparent to the JavaScript API
112
+
113
+ This optimization improves performance and battery usage
114
+ without affecting detection semantics or signal correctness.
115
+
116
+ > The cache never suppresses or hides detected integrity signals.
117
+
118
+ ---
119
+
120
+ ## Install
121
+
122
+ ```bash
123
+ pnpm add @cap-kit/integrity
124
+ # or
125
+ npm install @cap-kit/integrity
126
+ # or
127
+ yarn add @cap-kit/integrity
128
+ # then run:
129
+ npx cap sync
130
+ ```
131
+
132
+ ---
133
+
134
+ ## Native Configuration (Optional — Early Boot Enhancement)
135
+
136
+ To capture security signals at the earliest possible stage (before the Capacitor bridge is initialized), you can manually integrate the plugin into your App Host's native entry points. This is highly recommended for detecting advanced threats like Root/Jailbreak or early instrumentation.
137
+
138
+ ### When should you use native early boot integration?
139
+
140
+ Native early boot integration is **optional** and exists to improve
141
+ **signal timing**, not signal correctness.
142
+
143
+ You SHOULD consider this integration if:
144
+
145
+ - you want to observe potential root / jailbreak conditions
146
+ **as early as possible**
147
+ - you need visibility into instrumentation that may attach
148
+ before the JavaScript runtime starts
149
+ - you are building high-risk or security-sensitive applications
150
+
151
+ You do NOT need this integration if:
152
+
153
+ - you only require integrity signals during normal runtime
154
+ - you rely exclusively on `Integrity.check()` from JavaScript
155
+ - early detection timing is not critical for your use case
156
+
157
+ ### Android Integration
158
+
159
+ In your `MainActivity.kt`, call `IntegrityImpl.onApplicationCreate(context)` inside the `onCreate` method:
160
+
161
+ ```diff
162
+
163
+ package io.ionic.starter // Use your actual package name
164
+
165
+ import android.os.Bundle
166
+ import com.getcapacitor.BridgeActivity
167
+ + import io.capkit.integrity.IntegrityImpl
168
+
169
+ class MainActivity : BridgeActivity() {
170
+ override fun onCreate(savedInstanceState: Bundle?) {
171
+ + // Capture security signals during early boot
172
+ + IntegrityImpl.onApplicationCreate(this)
173
+
174
+ super.onCreate(savedInstanceState)
175
+ }
176
+ }
177
+
178
+ ```
179
+
180
+ ### iOS Integration
181
+
182
+ In your `AppDelegate.swift`, call `IntegrityImpl.onAppLaunch()` inside the `application(_:didFinishLaunchingWithOptions:)` method:
183
+
184
+ ```diff
185
+
186
+ import UIKit
187
+ import Capacitor
188
+ + import IntegrityPlugin // Import the plugin module
189
+
190
+ @UIApplicationMain
191
+ class AppDelegate: UIResponder, UIApplicationDelegate {
192
+
193
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
194
+
195
+ + // Capture security signals at the earliest stage possible
196
+ + IntegrityImpl.onAppLaunch()
197
+
198
+ return true
199
+ }
200
+ }
201
+
202
+ ```
203
+
204
+ > **Important**
205
+ >
206
+ > If native early boot integration is not performed:
207
+ >
208
+ > - the plugin remains fully functional
209
+ > - no integrity capability is lost
210
+ > - detection simply starts when the JavaScript layer invokes `Integrity.check()`
211
+ >
212
+ > Native integration improves **timing**, not **coverage**.
213
+
214
+ ---
215
+
216
+ ### Early boot signals (IMPORTANT)
217
+
218
+ When integrated at the native application entry points
219
+ (`MainActivity.onCreate` on Android, `AppDelegate.didFinishLaunchingWithOptions`
220
+ on iOS), the Integrity plugin may capture **early boot integrity signals**
221
+ before the Capacitor bridge is fully initialized.
222
+
223
+ IMPORTANT NOTES:
224
+
225
+ - Early boot signals are **best-effort** and opportunistic.
226
+ - They are **not guaranteed** to be captured on every app launch.
227
+ - Their absence MUST NOT be interpreted as a clean environment.
228
+ - They may be affected by:
229
+ - process restarts
230
+ - OS-level lifecycle optimizations
231
+ - multi-process behavior (Android)
232
+ - warm launches vs cold starts
233
+
234
+ Behavioral guarantees:
235
+
236
+ - Early boot signals are **merged into the first `Integrity.check()` report**
237
+ when available.
238
+ - If early boot integration is not performed, the plugin continues
239
+ to function correctly without them.
240
+ - Applications MUST NOT rely exclusively on early boot signals
241
+ for security decisions.
242
+
243
+ > Early boot detection improves visibility, not certainty.
244
+
245
+ ---
246
+
247
+ ## Configuration
248
+
249
+ Configuration is **static** and read **natively** from `capacitor.config`.
250
+
251
+ These values are:
252
+
253
+ - read once at plugin initialization
254
+ - immutable at runtime
255
+ - NOT accessible from JavaScript
256
+
257
+ Configuration options for the Integrity plugin.
258
+
259
+ | Prop | Type | Description | Default | Since |
260
+ | ------------------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ----- |
261
+ | **`verboseLogging`** | <code>boolean</code> | Enables verbose native logging. When enabled, additional debug information is printed to the native console (Logcat on Android, Xcode on iOS). This option affects native logging behavior only and has no impact on the JavaScript API or runtime behavior. | <code>false</code> | 8.0.0 |
262
+ | **`blockPage`** | <code>IntegrityBlockPageConfig</code> | Optional configuration for the integrity block page. This configuration controls the availability and source of a developer-provided HTML page that may be presented to the end user when the host application decides to do so. This configuration is: - read only by native code - immutable at runtime - NOT accessible from JavaScript The Integrity plugin will NEVER automatically present the block page. Presentation is always explicitly triggered by the host application via the public API. | | 8.0.0 |
263
+ | **`jailbreakUrlSchemes`** | <code>JailbreakUrlSchemesConfig</code> | Optional configuration for jailbreak URL scheme probing (iOS only). When enabled, the native iOS implementation may probe for known jailbreak-related applications using URL schemes such as `cydia://`. This configuration: - is read natively at runtime - is immutable - is NOT accessible from JavaScript - does NOT alter the public JavaScript API | | 8.0.0 |
264
+
265
+ ### Examples
266
+
267
+ In `capacitor.config.json`:
268
+
269
+ ```json
270
+ {
271
+ "plugins": {
272
+ "Integrity": {
273
+ "verboseLogging": true,
274
+ "blockPage": {
275
+ "enabled": true,
276
+ "url": "public/integrity-block.html"
277
+ },
278
+ "jailbreakUrlSchemes": {
279
+ "enabled": true,
280
+ "schemes": ["cydia", "sileo", "zbra"]
281
+ }
282
+ }
283
+ }
284
+ }
285
+ ```
286
+
287
+ In `capacitor.config.ts`:
288
+
289
+ ```ts
290
+ /// <reference types="@cap-kit/integrity" />
291
+
292
+ import { CapacitorConfig } from '@capacitor/cli';
293
+
294
+ const config: CapacitorConfig = {
295
+ plugins: {
296
+ Integrity: {
297
+ verboseLogging: true,
298
+ blockPage: {
299
+ enabled: true,
300
+ url: 'public/integrity-block.html',
301
+ },
302
+ jailbreakUrlSchemes: {
303
+ enabled: true,
304
+ schemes: ['cydia', 'sileo', 'zbra'],
305
+ },
306
+ },
307
+ },
308
+ };
309
+
310
+ export default config;
311
+ ```
312
+
313
+ ---
314
+
315
+ ### iOS Jailbreak URL Scheme Probing (Opt-In)
316
+
317
+ The Integrity plugin can optionally probe for known jailbreak-related
318
+ applications using URL schemes such as `cydia://`.
319
+
320
+ This feature is **disabled by default** and must be explicitly enabled
321
+ via native configuration.
322
+
323
+ #### Requirements
324
+
325
+ You MUST declare the queried schemes in `Info.plist`:
326
+
327
+ ```xml
328
+ <key>LSApplicationQueriesSchemes</key>
329
+ <array>
330
+ <string>cydia</string>
331
+ <string>sileo</string>
332
+ <string>zbra</string>
333
+ </array>
334
+ ```
335
+
336
+ ---
337
+
338
+ ## Usage
339
+
340
+ ### Basic integrity check
341
+
342
+ ```ts
343
+ import { Integrity } from '@cap-kit/integrity';
344
+
345
+ const report = await Integrity.check();
346
+
347
+ if (report.compromised) {
348
+ // Decide what to do
349
+ }
350
+ ```
351
+
352
+ ### Integrity check options
353
+
354
+ `Integrity.check()` accepts optional parameters that control
355
+ the strictness and verbosity of the integrity checks.
356
+
357
+ ```ts
358
+ const report = await Integrity.check({
359
+ level: 'standard',
360
+ includeDebugInfo: true,
361
+ });
362
+ ```
363
+
364
+ #### Options
365
+
366
+ | Option | Type | Default | Description |
367
+ | ------------------ | ----------------------------------- | --------- | ---------------------------------------------------- |
368
+ | `level` | `'basic' \| 'standard' \| 'strict'` | `'basic'` | Controls which categories of checks are executed |
369
+ | `includeDebugInfo` | `boolean` | `false` | Includes diagnostic descriptions in returned signals |
370
+
371
+ #### Levels behavior
372
+
373
+ - **basic**
374
+ - Root / jailbreak detection
375
+ - Emulator / simulator detection
376
+
377
+ - **standard**
378
+ - All `basic` checks
379
+ - Debugger / debug build detection
380
+ - Instrumentation / hooking heuristics (Frida, Substrate)
381
+ - **Memory map & Runtime image inspection**
382
+ - **Heuristic signal correlation**
383
+
384
+ - **strict**
385
+ - All `standard` checks
386
+ - Additional tamper and integrity heuristics
387
+ - Explicit reporting of unavailable platform attestation (observational only)
388
+
389
+ > ⚠️ The returned integrity score remains provisional and
390
+ > must not be used as the sole security decision signal.
391
+
392
+ ---
393
+
394
+ ### Presenting a block / warning page
395
+
396
+ The plugin will **never** present UI automatically.
397
+
398
+ UI presentation is always explicitly triggered by the host application.
399
+
400
+ ```ts
401
+ await Integrity.presentBlockPage({
402
+ reason: 'integrity_failed',
403
+ });
404
+ ```
405
+
406
+ #### Dismissible block page (optional)
407
+
408
+ By default, the block page is **not dismissible** (secure-by-default).
409
+
410
+ For demos, testing, or controlled environments, dismissal can be explicitly enabled:
411
+
412
+ ```ts
413
+ await Integrity.presentBlockPage({
414
+ reason: 'integrity_failed',
415
+ dismissible: true,
416
+ });
417
+ ```
418
+
419
+ Platform behavior:
420
+
421
+ | Platform | dismissible = false | dismissible = true |
422
+ | -------- | ---------------------- | ------------------------------- |
423
+ | Android | Back & close disabled | Native close button + back |
424
+ | iOS | Swipe & close disabled | Swipe-to-dismiss + native close |
425
+ | Web | Not supported | Not supported |
426
+
427
+ > ⚠️ In production environments, it is recommended to keep `dismissible` disabled.
428
+
429
+ ---
430
+
431
+ ## Error Handling
432
+
433
+ All Integrity methods use **Promise rejection** for error handling.
434
+
435
+ Errors are returned as a structured object:
436
+
437
+ ```ts
438
+ {
439
+ message: string;
440
+ code: IntegrityErrorCode;
441
+ }
442
+ ```
443
+
444
+ Error handling is **consistent across Android, iOS, and Web**.
445
+
446
+ ### Example
447
+
448
+ ```ts
449
+ import { Integrity, IntegrityErrorCode } from '@cap-kit/integrity';
450
+
451
+ try {
452
+ await Integrity.check();
453
+ } catch (e) {
454
+ if (e.code === IntegrityErrorCode.UNAVAILABLE) {
455
+ // Feature not available on this platform
456
+ }
457
+ }
458
+ ```
459
+
460
+ ---
461
+
462
+ ### Score Explanation Metadata
463
+
464
+ The Integrity plugin may include an optional `scoreExplanation`
465
+ field in the integrity report.
466
+
467
+ This field provides transparency about how the integrity score
468
+ was derived from detected signals.
469
+
470
+ #### Important notes
471
+
472
+ - This metadata is informational only.
473
+ - It does NOT alter the integrity score.
474
+ - It MUST NOT be treated as a security decision.
475
+ - Individual signals remain the authoritative source of truth.
476
+
477
+ ---
478
+
479
+ ## Web Platform Notes
480
+
481
+ The Web platform is supported to preserve API parity.
482
+
483
+ However, native integrity checks are **not available** in browser environments.
484
+
485
+ The following methods will reject with `IntegrityErrorCode.UNAVAILABLE` on Web:
486
+
487
+ - `Integrity.check()`
488
+ - `Integrity.presentBlockPage()`
489
+
490
+ `Integrity.getPluginVersion()` is always available.
491
+
492
+ ---
493
+
494
+ ## Permissions
495
+
496
+ ### Android
497
+
498
+ On Android, this plugin requires the `android.permission.INTERNET` permission. This permission is necessary for internal integrity checks, specifically for attempting socket connections to `localhost` with a controlled timeout to detect hooking frameworks like Frida.
499
+
500
+ This permission is automatically added to your `AndroidManifest.xml` via the plugin's native configuration.
501
+
502
+ #### Package Visibility (Android 11+)
503
+
504
+ To perform expanded root detection (scanning for apps like Magisk or SuperUser), the plugin declares a `<queries>` block in its manifest. This allow-list is required by Google Play policies to "see" security-related packages on devices with API level 30+.
505
+
506
+ **Note:** If your app is submitted to Google Play, you may need to justify the use of this expanded visibility during the app review process if you are targeting security-sensitive functionality.
507
+
508
+ ### iOS
509
+
510
+ No additional runtime permissions are required for iOS.
511
+
512
+ #### ⚠️ Toolchain Requirement
513
+
514
+ This plugin is designed exclusively for **Capacitor v8**. In accordance with the global strict rules for this version, **Xcode 26 is the MANDATORY requirement** for building the iOS native implementation.
515
+
516
+ Any issues or behaviors observed on Xcode 15, 16, or earlier versions are considered environment misconfigurations and are not supported by the plugin.
517
+
518
+ ---
519
+
520
+ ## API
521
+
522
+ The public API is fully typed and documented via TypeScript definitions.
523
+
524
+ See `definitions.ts` for the complete contract.
525
+
526
+ <docgen-index>
527
+
528
+ * [`check(...)`](#check)
529
+ * [`presentBlockPage(...)`](#presentblockpage)
530
+ * [`getPluginVersion()`](#getpluginversion)
531
+ * [`addListener('integritySignal', ...)`](#addlistenerintegritysignal-)
532
+ * [`removeAllListeners()`](#removealllisteners)
533
+ * [Interfaces](#interfaces)
534
+ * [Type Aliases](#type-aliases)
535
+ * [Enums](#enums)
536
+
537
+ </docgen-index>
538
+
539
+ <docgen-api>
540
+ <!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
541
+
542
+ Public JavaScript API for the Integrity Capacitor plugin.
543
+
544
+ This interface defines a stable, platform-agnostic API.
545
+ All methods behave consistently across Android, iOS, and Web.
546
+
547
+ ### check(...)
548
+
549
+ ```typescript
550
+ check(options?: IntegrityCheckOptions | undefined) => Promise<IntegrityReport>
551
+ ```
552
+
553
+ Executes a runtime integrity check.
554
+
555
+ | Param | Type |
556
+ | ------------- | ----------------------------------------------------------------------- |
557
+ | **`options`** | <code><a href="#integritycheckoptions">IntegrityCheckOptions</a></code> |
558
+
559
+ **Returns:** <code>Promise&lt;<a href="#integrityreport">IntegrityReport</a>&gt;</code>
560
+
561
+ **Since:** 8.0.0
562
+
563
+ #### Example
564
+
565
+ ```ts
566
+ const report = await Integrity.check();
567
+ ```
568
+
569
+ --------------------
570
+
571
+
572
+ ### presentBlockPage(...)
573
+
574
+ ```typescript
575
+ presentBlockPage(options?: PresentBlockPageOptions | undefined) => Promise<PresentBlockPageResult>
576
+ ```
577
+
578
+ Presents the configured integrity block page, if enabled.
579
+
580
+ The plugin never decides *when* this method should be called.
581
+ Invocation is entirely controlled by the host application.
582
+
583
+ | Param | Type |
584
+ | ------------- | --------------------------------------------------------------------------- |
585
+ | **`options`** | <code><a href="#presentblockpageoptions">PresentBlockPageOptions</a></code> |
586
+
587
+ **Returns:** <code>Promise&lt;<a href="#presentblockpageresult">PresentBlockPageResult</a>&gt;</code>
588
+
589
+ **Since:** 8.0.0
590
+
591
+ #### Example
592
+
593
+ ```ts
594
+ await Integrity.presentBlockPage({ reason: 'integrity_failed' });
595
+ ```
596
+
597
+ --------------------
598
+
599
+
600
+ ### getPluginVersion()
601
+
602
+ ```typescript
603
+ getPluginVersion() => Promise<PluginVersionResult>
604
+ ```
605
+
606
+ Returns the native plugin version.
607
+
608
+ The returned version corresponds to the native implementation
609
+ bundled with the application.
610
+
611
+ **Returns:** <code>Promise&lt;<a href="#pluginversionresult">PluginVersionResult</a>&gt;</code>
612
+
613
+ **Since:** 8.0.0
614
+
615
+ #### Example
616
+
617
+ ```ts
618
+ const { version } = await Integrity.getPluginVersion();
619
+ ```
620
+
621
+ --------------------
622
+
623
+
624
+ ### addListener('integritySignal', ...)
625
+
626
+ ```typescript
627
+ addListener(eventName: 'integritySignal', listenerFunc: (signal: IntegritySignalEvent) => void) => Promise<PluginListenerHandle>
628
+ ```
629
+
630
+ Registers a listener for real-time integrity signals.
631
+
632
+ The provided callback is invoked every time a new integrity
633
+ signal is detected by the native layer.
634
+
635
+ BEHAVIOR:
636
+ - Signals may be emitted at any time after plugin initialization.
637
+ - Signals detected before listener registration MAY be delivered
638
+ immediately after registration.
639
+ - No guarantees are made about signal frequency or ordering
640
+ across platforms.
641
+
642
+ IMPORTANT:
643
+ - This listener is non-blocking.
644
+ - The plugin does NOT enforce any policy based on signals.
645
+
646
+ | Param | Type | Description |
647
+ | ------------------ | -------------------------------------------------------------------------------- | -------------------------------------------- |
648
+ | **`eventName`** | <code>'integritySignal'</code> | The event to listen for ('integritySignal'). |
649
+ | **`listenerFunc`** | <code>(signal: <a href="#integritysignal">IntegritySignal</a>) =&gt; void</code> | Callback invoked with the detected signal. |
650
+
651
+ **Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt;</code>
652
+
653
+ **Since:** 8.0.0
654
+
655
+ --------------------
656
+
657
+
658
+ ### removeAllListeners()
659
+
660
+ ```typescript
661
+ removeAllListeners() => Promise<void>
662
+ ```
663
+
664
+ Removes all registered listeners for this plugin.
665
+
666
+ NOTE:
667
+ - Removing listeners does NOT stop signal detection natively.
668
+ - Signals may continue to be detected and buffered
669
+ until a listener is registered again.
670
+
671
+ **Since:** 8.0.0
672
+
673
+ --------------------
674
+
675
+
676
+ ### Interfaces
677
+
678
+
679
+ #### IntegrityReport
680
+
681
+ Result object returned by `Integrity.check()`.
682
+
683
+ This object aggregates all detected signals
684
+ and provides a provisional integrity score.
685
+
686
+ | Prop | Type | Description | Since |
687
+ | ---------------------- | ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
688
+ | **`compromised`** | <code>boolean</code> | Indicates whether the environment is considered compromised according to the current scoring model. | |
689
+ | **`score`** | <code>number</code> | Provisional integrity score. The score ranges from 0 to 100 and is derived from the detected signals. | |
690
+ | **`signals`** | <code>IntegritySignal[]</code> | List of detected integrity signals. | |
691
+ | **`environment`** | <code><a href="#integrityenvironment">IntegrityEnvironment</a></code> | Execution environment summary. | |
692
+ | **`timestamp`** | <code>number</code> | Unix timestamp (milliseconds) when the check was performed. | |
693
+ | **`scoreExplanation`** | <code><a href="#integrityscoreexplanation">IntegrityScoreExplanation</a></code> | Optional explanation metadata describing how the integrity score was derived from the detected signals. This field is informational only and MUST NOT be treated as a security decision or enforcement mechanism. | 8.0.0 |
694
+
695
+
696
+ #### IntegritySignal
697
+
698
+ A single integrity signal detected on the current device.
699
+
700
+ Signals represent *observations*, not decisions.
701
+ Multiple signals MAY be combined by the host application
702
+ to derive a security policy.
703
+
704
+ Signals:
705
+ - are emitted asynchronously
706
+ - may occur at any time during the app lifecycle
707
+ - may be emitted before or after the first call to `check()`
708
+
709
+ | Prop | Type | Description |
710
+ | ----------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
711
+ | **`id`** | <code>string</code> | Stable identifier for the signal. This value: - is stable across releases - MUST NOT be parsed or pattern-matched - is intended for analytics, logging, and policy evaluation |
712
+ | **`category`** | <code><a href="#integritysignalcategory">IntegritySignalCategory</a></code> | High-level category of the signal. Categories allow grouping related signals without relying on specific identifiers. |
713
+ | **`confidence`** | <code><a href="#integrityconfidencelevel">IntegrityConfidenceLevel</a></code> | Confidence level of the detection. This value expresses how strongly the signal correlates with a potentially compromised or risky environment. NOTE: Although typed as a string union in the public API, native implementations MUST only emit values defined by the internal <a href="#integrityconfidencelevel">IntegrityConfidenceLevel</a> enum. |
714
+ | **`description`** | <code>string</code> | Optional human-readable description. This field: - is intended for diagnostics and debugging only - MAY be omitted or redacted in production builds - MUST NOT be relied upon programmatically |
715
+ | **`metadata`** | <code>Record&lt;string, string \| number \| boolean&gt;</code> | Additional diagnostic metadata associated with the signal. Metadata provides granular details about the detection (e.g. matched filesystem paths, runtime artifacts, or environment properties) without altering the stable signal identifier. IMPORTANT: - Metadata is informational only. - Keys and values are NOT guaranteed to be stable. - Applications MUST NOT rely on specific metadata fields for security decisions. |
716
+
717
+
718
+ #### IntegrityEnvironment
719
+
720
+ Summary of the execution environment in which
721
+ the integrity check was performed.
722
+
723
+ | Prop | Type | Description |
724
+ | ------------------ | ---------------------------------------- | ----------------------------------------------------------------------------- |
725
+ | **`platform`** | <code>'ios' \| 'android' \| 'web'</code> | Current platform. |
726
+ | **`isEmulator`** | <code>boolean</code> | Indicates whether the app is running in an emulator or simulator environment. |
727
+ | **`isDebugBuild`** | <code>boolean</code> | Indicates whether the app was built in debug/development mode. |
728
+
729
+
730
+ #### IntegrityScoreExplanation
731
+
732
+ Describes how the integrity score was derived.
733
+
734
+ This structure provides transparency and auditability
735
+ without exposing internal scoring algorithms.
736
+
737
+ | Prop | Type | Description |
738
+ | ------------------ | ----------------------------------------------------------- | --------------------------------------------------------- |
739
+ | **`totalSignals`** | <code>number</code> | Total number of detected signals. |
740
+ | **`byConfidence`** | <code>{ high: number; medium: number; low: number; }</code> | Breakdown of signals by confidence level. |
741
+ | **`contributors`** | <code>string[]</code> | List of signal identifiers that contributed to the score. |
742
+
743
+
744
+ #### IntegrityCheckOptions
745
+
746
+ Options controlling the behavior of `Integrity.check()`.
747
+
748
+ These options influence *how* checks are performed,
749
+ not *what* the public API returns.
750
+
751
+ | Prop | Type | Description |
752
+ | ---------------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
753
+ | **`level`** | <code>'basic' \| 'standard' \| 'strict'</code> | Desired strictness level. Higher levels may enable additional heuristics at the cost of performance. |
754
+ | **`includeDebugInfo`** | <code>boolean</code> | Includes additional debug information in the returned signals when enabled. |
755
+
756
+
757
+ #### PresentBlockPageResult
758
+
759
+ Result object returned by `presentBlockPage()`.
760
+
761
+ | Prop | Type | Description |
762
+ | --------------- | -------------------- | -------------------------------------------------------- |
763
+ | **`presented`** | <code>boolean</code> | Indicates whether the block page was actually presented. |
764
+
765
+
766
+ #### PresentBlockPageOptions
767
+
768
+ Options for presenting the integrity block page.
769
+
770
+ | Prop | Type | Description | Default | Since |
771
+ | ----------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------ | ----- |
772
+ | **`reason`** | <code>string</code> | Optional reason code passed to the block page. This value may be used for analytics, localization, or user messaging. | | 8.0.0 |
773
+ | **`dismissible`** | <code>boolean</code> | Whether the block page can be dismissed by the user. Defaults to false. In production environments, this should typically remain disabled. | <code>false</code> | 8.0.0 |
774
+
775
+
776
+ #### PluginVersionResult
777
+
778
+ Result returned by the getPluginVersion method.
779
+
780
+ | Prop | Type | Description |
781
+ | ------------- | ------------------- | ---------------------------------------- |
782
+ | **`version`** | <code>string</code> | The native version string of the plugin. |
783
+
784
+
785
+ #### PluginListenerHandle
786
+
787
+ | Prop | Type |
788
+ | ------------ | ----------------------------------------- |
789
+ | **`remove`** | <code>() =&gt; Promise&lt;void&gt;</code> |
790
+
791
+
792
+ ### Type Aliases
793
+
794
+
795
+ #### IntegritySignalCategory
796
+
797
+ Category of a detected integrity signal.
798
+
799
+ Categories are intentionally broad and stable.
800
+ New detection techniques MUST reuse existing categories
801
+ whenever possible to avoid breaking consumers.
802
+
803
+ <code>'root' | 'jailbreak' | 'emulator' | 'debug' | 'hook' | 'tamper' | 'environment'</code>
804
+
805
+
806
+ #### IntegritySignalEvent
807
+
808
+ Event payload emitted when a new integrity signal is detected.
809
+
810
+ This event represents a *real-time observation* of a potential
811
+ integrity-relevant condition on the device.
812
+
813
+ IMPORTANT:
814
+ - Signals are observational only.
815
+ - Emitting a signal does NOT imply that the environment is compromised.
816
+ - No blocking or enforcement is performed by the plugin.
817
+
818
+ The host application is responsible for:
819
+ - interpreting signals
820
+ - correlating multiple signals
821
+ - applying any security or UX policy
822
+
823
+ <code><a href="#integritysignal">IntegritySignal</a></code>
824
+
825
+
826
+ ### Enums
827
+
828
+
829
+ #### IntegrityConfidenceLevel
830
+
831
+ | Members | Value |
832
+ | ------------ | --------------------- |
833
+ | **`LOW`** | <code>'low'</code> |
834
+ | **`MEDIUM`** | <code>'medium'</code> |
835
+ | **`HIGH`** | <code>'high'</code> |
836
+
837
+ </docgen-api>
838
+
839
+ ---
840
+
841
+ ## Integrity events semantics (IMPORTANT)
842
+
843
+ The `integritySignal` event documented above represents a
844
+ **real-time observational snapshot**, not an incremental update.
845
+
846
+ Important clarifications:
847
+
848
+ - Integrity events **may include signals already returned**
849
+ by a previous `Integrity.check()` call.
850
+ - Events are **NOT incremental** and **NOT deltas**.
851
+ - Each emitted event is a **standalone integrity observation**
852
+ produced at a specific moment in time.
853
+
854
+ Implications for applications:
855
+
856
+ - Consumers MUST be prepared to receive duplicate signals.
857
+ - Applications SHOULD implement their own de-duplication or
858
+ correlation logic if required.
859
+ - Events MUST NOT be interpreted as a continuous stream of
860
+ unique integrity changes.
861
+
862
+ > Events report observations, not transitions.
863
+
864
+ ---
865
+
866
+ ### Cross-correlation: Jailbreak + Hooking (iOS)
867
+
868
+ The Integrity plugin may emit a derived signal when it detects
869
+ both jailbreak indicators and runtime hooking signals during
870
+ the same execution window.
871
+
872
+ This signal represents a **cross-category correlation**, indicating
873
+ that the device is not only modified but also actively instrumented.
874
+
875
+ #### Signal details
876
+
877
+ - **id**: `ios_jailbreak_and_hook_detected`
878
+ - **category**: `tamper`
879
+ - **confidence**: `high`
880
+
881
+ #### Important notes
882
+
883
+ - This signal is observational only.
884
+ - It does not replace or suppress individual signals.
885
+ - It must not be treated as an automatic enforcement trigger.
886
+
887
+ ---
888
+
889
+ ## Limitations
890
+
891
+ - **Heuristic Bypass**: Root / jailbreak detection can be bypassed by advanced cloaking tools.
892
+ - **Package Scanning**: Root detection on Android includes scanning for known management apps (e.g., Magisk). This is subject to OS-level package visibility restrictions.
893
+ - **Emulator Detection**: Detection is heuristic and relies on build properties that may vary between providers.
894
+ - Frida detection uses memory and runtime inspection
895
+ - **No cryptographic or remote attestation is performed**
896
+ - **Apple App Attest and Google Play Integrity are NOT implemented**
897
+ - Attestation-related signals, when present, explicitly report unavailability
898
+ - No device identity is established
899
+
900
+ These limitations are **intentional** to:
901
+
902
+ - avoid store policy violations
903
+ - reduce false positives
904
+ - keep the plugin portable and maintainable
905
+
906
+ ### Debug environment detection
907
+
908
+ The plugin provides parity between platforms for debug detection. A `debug` integrity signal is reported when:
909
+
910
+ - **Debugger Attached**: A debugger is currently attached to the running process (detected via `Debug.isDebuggerConnected()` on Android or `sysctl` on iOS).
911
+ - **Debuggable Environment**: The application is running in a debuggable state or signed with a development profile (detected via `FLAG_DEBUGGABLE` on Android or `get-task-allow` entitlement on iOS).
912
+
913
+ This signal is **informational only** and does not necessarily
914
+ indicate a compromised device.
915
+
916
+ Consumers MUST interpret debug signals in context and
917
+ combine them with other integrity signals.
918
+
919
+ ### Hooking detection signal behavior (iOS)
920
+
921
+ On iOS, runtime hooking detection is intentionally designed to emit
922
+ **at most one hooking-related signal per check execution**.
923
+
924
+ Design characteristics:
925
+
926
+ - The detector stops at the **first confirmed hooking artifact**.
927
+ - Only a single signal is emitted, even if multiple suspicious
928
+ libraries or runtime indicators are present.
929
+ - This behavior is **intentional** and optimized for:
930
+ - low noise
931
+ - predictable signal volume
932
+ - reduced false-positive amplification
933
+
934
+ Implications:
935
+
936
+ - The absence of multiple hooking signals does **not** imply
937
+ that only one artifact was present.
938
+ - Diagnostic depth is intentionally limited in favor of
939
+ stability and signal clarity.
940
+
941
+ > This is a design choice, not a detection limitation.
942
+
943
+ ---
944
+
945
+ ## 🔒 Integrity philosophy
946
+
947
+ ### Observation, not enforcement
948
+
949
+ The Integrity plugin is designed as an **observation layer**, not as an enforcement or decision engine.
950
+
951
+ Its responsibility is to **detect and report runtime integrity signals** in a consistent, cross-platform way.
952
+ It deliberately **does not decide what action should be taken** when a signal is detected.
953
+
954
+ This design allows applications to:
955
+
956
+ - define their own security policies
957
+ - adapt behavior to different environments
958
+ - avoid hard-coded or platform-specific assumptions
959
+
960
+ In short:
961
+
962
+ > **The plugin observes.
963
+ > The application decides.**
964
+
965
+ ---
966
+
967
+ ## 🧩 Why there are no single-purpose checks
968
+
969
+ The public API intentionally exposes a **single entry point**:
970
+
971
+ ```ts
972
+ Integrity.check(options?)
973
+ ```
974
+
975
+ Rather than providing individual methods such as:
976
+
977
+ - `checkRoot()`
978
+ - `checkEmulator()`
979
+ - `checkDebug()`
980
+
981
+ the plugin returns a **structured integrity report** containing multiple **signals**, each classified by:
982
+
983
+ - category (e.g. root, emulator, debug, hook, tamper)
984
+ - confidence level (low / medium / high)
985
+
986
+ This approach avoids:
987
+
988
+ - API fragmentation
989
+ - platform-specific behavior leaks
990
+ - misuse of isolated checks
991
+ - rigid or unsafe security decisions
992
+
993
+ Applications can still derive fine-grained logic by inspecting the returned signals:
994
+
995
+ ```ts
996
+ const hasRoot = report.signals.some((s) => s.category === 'root');
997
+ const hasEmulator = report.signals.some((s) => s.category === 'emulator');
998
+ ```
999
+
1000
+ This keeps the API **stable, extensible, and policy-agnostic**.
1001
+
1002
+ ---
1003
+
1004
+ ## 🧠 Integrity levels
1005
+
1006
+ Instead of selecting individual checks, applications choose a **strictness level**:
1007
+
1008
+ - **basic** – lightweight and safe checks
1009
+ - **standard** – includes debug and hooking detection
1010
+ - **strict** – adds tampering and signature integrity checks
1011
+
1012
+ The selected level controls **how deeply the environment is inspected**, not which single signal is exposed.
1013
+
1014
+ ---
1015
+
1016
+ ## Score interpretation (IMPORTANT)
1017
+
1018
+ The integrity `score` returned by `Integrity.check()` is a **heuristic indicator**, not a guarantee.
1019
+
1020
+ Key points:
1021
+
1022
+ - The score is derived from detected integrity signals and their confidence levels.
1023
+ - A score **greater than or equal to 30** currently marks the environment as `compromised`.
1024
+ - This threshold is **internal, heuristic-based, and subject to change**.
1025
+ - The score **must NOT** be treated as:
1026
+ - a security guarantee
1027
+ - a cryptographic proof
1028
+ - a definitive compromise verdict
1029
+
1030
+ Applications MUST:
1031
+
1032
+ - interpret the score in context
1033
+ - combine it with individual signals
1034
+ - apply their own business or security logic
1035
+
1036
+ > ⚠️ Do not rely on the score alone to make irreversible security decisions.
1037
+
1038
+ ---
1039
+
1040
+ ## 🔮 Future extensibility
1041
+
1042
+ The current API focuses on a clean and minimal surface, but the architecture is designed to be **extensible**.
1043
+
1044
+ In the future, the plugin may introduce:
1045
+
1046
+ - more advanced signal classification
1047
+ - additional integrity signals
1048
+ - configurable inclusion or exclusion of signal groups
1049
+ - richer metadata for diagnostics and auditing
1050
+
1051
+ Any future extension will preserve the same core principle:
1052
+
1053
+ - **one entry point**
1054
+ - **no forced policy**
1055
+ - **no platform-specific leakage**
1056
+
1057
+ Applications should always remain in full control of how integrity information is interpreted and enforced.
1058
+
1059
+ ---
1060
+
1061
+ ## ✅ Summary
1062
+
1063
+ - The Integrity plugin **detects signals**, it does not block or enforce
1064
+ - Security decisions are **always owned by the application**
1065
+ - The API is designed for **long-term stability and flexibility**
1066
+ - Future enhancements will extend capabilities without breaking this model
1067
+
1068
+ ---
1069
+
1070
+ ## Roadmap (Non-binding)
1071
+
1072
+ > The roadmap below is indicative and non-binding.
1073
+ > Items may be implemented across multiple `next.x` iterations.
1074
+
1075
+ - Optional platform attestation helpers
1076
+ - Extended tamper heuristics
1077
+ - Improved scoring models
1078
+ - Documentation examples
1079
+
1080
+ ---
1081
+
1082
+ ## Contributing
1083
+
1084
+ Contributions are welcome! Please read the
1085
+ [contributing guide](CONTRIBUTING.md)
1086
+ before submitting a pull request.
1087
+
1088
+ ---
1089
+
1090
+ ## Credits
1091
+
1092
+ This plugin is based on prior work from the Community and
1093
+ has been refactored and modernized for **Capacitor v8** and
1094
+ **Swift Package Manager** compatibility.
1095
+
1096
+ Original inspiration:
1097
+
1098
+ - [https://github.com/capacitor-community/device-security-detect](https://github.com/capacitor-community/device-security-detect)
1099
+
1100
+ ---
1101
+
1102
+ ## License
1103
+
1104
+ MIT