idmission-web-sdk 2.3.212 → 2.3.213

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.
@@ -1,4 +1,8 @@
1
1
  import { type MediaIntegrityToken } from './getUserMediaIntegrity';
2
+ type TamperOptions = {
3
+ enabled?: boolean;
4
+ token?: MediaIntegrityToken;
5
+ };
2
6
  export type Camera = {
3
7
  stream: MediaStream;
4
8
  isRearFacing: boolean;
@@ -8,8 +12,8 @@ export type Camera = {
8
12
  height: number;
9
13
  };
10
14
  export type CameraResolution = 'LOW' | 'MID' | 'MAX';
11
- export declare function selectAndOpenCamera(resolution?: CameraResolution, token?: MediaIntegrityToken): Promise<Camera>;
12
- export declare function getVideoDeviceMaxDimensions(deviceInfo: MediaDeviceInfo, token?: MediaIntegrityToken): Promise<{
15
+ export declare function selectAndOpenCamera(resolution?: CameraResolution, tamper?: TamperOptions): Promise<Camera>;
16
+ export declare function getVideoDeviceMaxDimensions(deviceInfo: MediaDeviceInfo, tamper?: TamperOptions): Promise<{
13
17
  width: number;
14
18
  height: number;
15
19
  }>;
@@ -21,7 +25,7 @@ type Resolution = {
21
25
  };
22
26
  export declare const quickScan: Resolution[];
23
27
  export type FacingMode = 'user' | 'environment' | 'left' | 'right';
24
- export declare function listAvailableCameras(facingMode?: FacingMode, requestMicAccess?: boolean, token?: MediaIntegrityToken): Promise<MediaDeviceInfo[]>;
28
+ export declare function listAvailableCameras(facingMode?: FacingMode, requestMicAccess?: boolean, tamper?: TamperOptions): Promise<MediaDeviceInfo[]>;
25
29
  export declare const frontCameraLabels: string[];
26
30
  export declare const rearCameraLabels: string[];
27
31
  export declare const backUltraWideCameraLabels: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"Camera.d.ts","sourceRoot":"","sources":["../../../src/lib/camera/Camera.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAIrF,MAAM,MAAM,MAAM,GAAG;IACnB,MAAM,EAAE,WAAW,CAAA;IACnB,YAAY,EAAE,OAAO,CAAA;IACrB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAA;AAIpD,wBAAsB,mBAAmB,CACvC,UAAU,GAAE,gBAAwB,EACpC,KAAK,CAAC,EAAE,mBAAmB,GAC1B,OAAO,CAAC,MAAM,CAAC,CA2GjB;AAQD,wBAAsB,2BAA2B,CAC/C,UAAU,EAAE,eAAe,EAC3B,KAAK,CAAC,EAAE,mBAAmB,GAC1B,OAAO,CAAC;IACT,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAC,CAkBD;AAED,KAAK,UAAU,GAAG;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AACD,eAAO,MAAM,SAAS,EAAE,UAAU,EAmEjC,CAAA;AAyFD,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,aAAa,GAAG,MAAM,GAAG,OAAO,CAAA;AAElE,wBAAsB,oBAAoB,CACxC,UAAU,CAAC,EAAE,UAAU,EACvB,gBAAgB,GAAE,OAAe,EACjC,KAAK,CAAC,EAAE,mBAAmB,GAC1B,OAAO,CAAC,eAAe,EAAE,CAAC,CA2B5B;AAED,eAAO,MAAM,iBAAiB,UA+ByB,CAAA;AACvD,eAAO,MAAM,gBAAgB,UAoC0B,CAAA;AACvD,eAAO,MAAM,yBAAyB,UAqCiB,CAAA;AAEvD,eAAO,MAAM,kBAAkB,kBACd,MAAM,GAAG,eAAe,mBACtB,MAAM,GAAG,MAAM,EAAE,YAWnC,CAAA;AAQD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,gBAAgB,GAAG,IAAI,GAC9B,MAAM,CA6CR;AAED,wBAAgB,mBAAmB,SAKlC;AAED,wBAAgB,uBAAuB,SAQtC"}
1
+ {"version":3,"file":"Camera.d.ts","sourceRoot":"","sources":["../../../src/lib/camera/Camera.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAIrF,KAAK,aAAa,GAAG;IACnB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,mBAAmB,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,MAAM,GAAG;IACnB,MAAM,EAAE,WAAW,CAAA;IACnB,YAAY,EAAE,OAAO,CAAA;IACrB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAA;AAIpD,wBAAsB,mBAAmB,CACvC,UAAU,GAAE,gBAAwB,EACpC,MAAM,GAAE,aAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,CA2GjB;AAQD,wBAAsB,2BAA2B,CAC/C,UAAU,EAAE,eAAe,EAC3B,MAAM,GAAE,aAAkB,GACzB,OAAO,CAAC;IACT,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAC,CAkBD;AAED,KAAK,UAAU,GAAG;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AACD,eAAO,MAAM,SAAS,EAAE,UAAU,EAmEjC,CAAA;AAyFD,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,aAAa,GAAG,MAAM,GAAG,OAAO,CAAA;AAElE,wBAAsB,oBAAoB,CACxC,UAAU,CAAC,EAAE,UAAU,EACvB,gBAAgB,GAAE,OAAe,EACjC,MAAM,GAAE,aAAkB,GACzB,OAAO,CAAC,eAAe,EAAE,CAAC,CA2B5B;AAED,eAAO,MAAM,iBAAiB,UA+ByB,CAAA;AACvD,eAAO,MAAM,gBAAgB,UAoC0B,CAAA;AACvD,eAAO,MAAM,yBAAyB,UAqCiB,CAAA;AAEvD,eAAO,MAAM,kBAAkB,kBACd,MAAM,GAAG,eAAe,mBACtB,MAAM,GAAG,MAAM,EAAE,YAWnC,CAAA;AAQD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,gBAAgB,GAAG,IAAI,GAC9B,MAAM,CA6CR;AAED,wBAAgB,mBAAmB,SAKlC;AAED,wBAAgB,uBAAuB,SAQtC"}
@@ -1 +1 @@
1
- {"version":3,"file":"cameraStore.d.ts","sourceRoot":"","sources":["../../../src/lib/camera/cameraStore.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cameraStore.d.ts","sourceRoot":"","sources":["../../../src/lib/camera/cameraStore.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAEZ,gBAAgB,EAChB,SAAS,EACT,cAAc,EAIf,MAAM,OAAO,CAAA;AAEd,OAAO,EAEL,MAAM,EAMP,MAAM,UAAU,CAAA;AAMjB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAQlE,eAAO,IAAI,MAAM,EAAE,MAAM,GAAG,IAAW,CAAA;AACvC,eAAO,IAAI,WAAW,EAAE,WAAW,GAAG,IAAW,CAAA;AACjD,eAAO,IAAI,WAAW,EAAE,WAAW,GAAG,IAAW,CAAA;AAEjD,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE,gBAAgB,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAA;IAEnD,0BAA0B,CAAC,EAAE,OAAO,CAAA;IACpC,4BAA4B,CAAC,EAAE,OAAO,CAAA;IACtC,uBAAuB,CAAC,EAAE,OAAO,CAAA;IAEjC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAA;IACjC,wBAAwB,CAAC,EAAE,MAAM,IAAI,CAAA;IAErC,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;CAC1C,CAAA;AAED,MAAM,MAAM,WAAW,GAAG,iBAAiB,GAAG;IAC5C,WAAW,EAAE,OAAO,CAAA;IACpB,WAAW,EAAE,eAAe,GAAG,IAAI,CAAA;IACnC,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IAEnB,YAAY,EAAE,OAAO,CAAA;IAErB,WAAW,EAAE,OAAO,CAAA;IACpB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,+BAA+B,EAAE,OAAO,CAAA;IACxC,4BAA4B,EAAE,OAAO,CAAA;IACrC,4BAA4B,EAAE,OAAO,CAAA;IACrC,qBAAqB,EAAE,OAAO,CAAA;IAC9B,uBAAuB,EAAE,OAAO,CAAA;IAEhC,eAAe,EAAE,OAAO,CAAA;IACxB,sBAAsB,EAAE,OAAO,CAAA;CAChC,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAA;IAE9C,cAAc,EAAE,CAAC,CAAC,EAAE,cAAc,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAA;IAC7D,gCAAgC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IAE1D,mBAAmB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACxC,mBAAmB,EAAE,MAAM,IAAI,CAAA;IAE/B,uBAAuB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5C,uBAAuB,EAAE,MAAM,IAAI,CAAA;CACpC,CAAA;AAmXD,MAAM,MAAM,6BAA6B,GAAG;IAC1C,gBAAgB,CAAC,EAAE,0BAA0B,CAAA;CAC9C,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,gBAAgB,CAAC,EAAE,wBAAwB,CAAA;CAC5C,CAAA;AAKD,wBAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,0BAAiC,EACjC,4BAAmC,EACnC,uBAA+B,EAC/B,aAAoB,EACpB,MAAM,EACN,oBAAoB,EACpB,yBAAyB,EACzB,2BAA2B,EAC3B,wBAAwB,EACxB,uBAA+B,EAC/B,qBAA6B,EAC7B,mBAAmB,EACnB,UAAe,EACf,QAAa,GACd,EAAE;IACD,QAAQ,EAAE,SAAS,CAAA;IACnB,0BAA0B,CAAC,EAAE,OAAO,CAAA;IACpC,4BAA4B,CAAC,EAAE,OAAO,CAAA;IACtC,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAA;IACjC,yBAAyB,CAAC,EAAE,MAAM,IAAI,CAAA;IACtC,2BAA2B,CAAC,EAAE,MAAM,IAAI,CAAA;IACxC,wBAAwB,CAAC,EAAE,MAAM,IAAI,CAAA;IACrC,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,mFAAmF;IACnF,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;IACzC,UAAU,CAAC,EAAE,6BAA6B,CAAA;IAC1C,QAAQ,CAAC,EAAE,2BAA2B,CAAA;CACvC,qBAwEA;AAED,KAAK,0BAA0B,GAAG;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,KAAK,wBAAwB,GAAG;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AA8GD,wBAAgB,cAAc,IAAI,WAAW,GAAG,aAAa,CAAA;AAC7D,wBAAgB,cAAc,CAAC,CAAC,EAC9B,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,GAAG,aAAa,KAAK,CAAC,GAClD,CAAC,CAAA"}
@@ -12,20 +12,61 @@ export type IntegrityResult = {
12
12
  * Customers should call this as early as possible in their application boot,
13
13
  * before any third-party scripts have a chance to monkey-patch browser APIs.
14
14
  *
15
- * The returned token is passed to SDK components via the `mediaIntegrityToken` prop.
15
+ * The returned token is passed to SDK components via the `mediaIntegrityToken`
16
+ * prop. **Passing a token is the recommended way to enable strong tamper
17
+ * detection.** Without it, the SDK falls back to Layer 1 (boot-time reference
18
+ * snapshot) and Layer 2 (page-vs-iframe `toString` heuristic), both of which
19
+ * are best-effort and can produce false positives — e.g. legitimate post-init
20
+ * shims like `webrtc-adapter`, browser-level instrumentation in Chrome for
21
+ * iOS (CriOS), and some browser extensions all replace `getUserMedia` in ways
22
+ * that look indistinguishable from tampering at those layers.
23
+ *
24
+ * Layer 3 (this token) compares against a snapshot the customer captures at
25
+ * a moment of their choosing, so it is robust against post-capture tampering
26
+ * regardless of how sophisticated the attacker is at faking `[native code]`
27
+ * after the snapshot — but it cannot defend against tampering that already
28
+ * happened before `captureMediaIntegrity` ran. Capture early.
29
+ *
30
+ * **Must be called in a browser context** (`navigator.mediaDevices` available).
31
+ * Calling during SSR / pre-DOM produces a token whose snapshot is empty;
32
+ * subsequent integrity checks against such a token will report "unrecognized
33
+ * or forged token" — a false positive caused by capture-time misuse.
16
34
  */
17
35
  export declare function captureMediaIntegrity(): MediaIntegrityToken;
36
+ export type IntegrityCheckOptions = {
37
+ /** When false or omitted, all checks are skipped and result is clean. */
38
+ enabled?: boolean;
39
+ /** Optional customer-captured token for Layer 3. */
40
+ token?: MediaIntegrityToken;
41
+ };
18
42
  /**
19
43
  * Run all applicable integrity check layers.
20
- * Layer 1: Boot-time referential equality
21
- * Layer 2: Fresh iframe cross-context toString (async-safe but sync)
22
- * Layer 3: Customer-provided token validation (if token supplied)
44
+ *
45
+ * - **Layer 1**: Boot-time referential equality (corroborated by Layer 2).
46
+ * Best-effort; misses attackers who inject before SDK load.
47
+ * - **Layer 2**: Fresh-iframe cross-realm `toString` comparison. Best-effort;
48
+ * produces false positives in browser-level instrumentation contexts (CriOS,
49
+ * extensions). The page-vs-iframe disagreement case is gated on iframe
50
+ * trustworthiness to mitigate this.
51
+ * - **Layer 3**: Customer-provided token validation (only runs when a token
52
+ * is supplied). **This is the strong defense** — see `captureMediaIntegrity`.
53
+ *
54
+ * Returns clean immediately if `enabled` is not true.
23
55
  */
24
- export declare function checkGetUserMediaIntegrity(token?: MediaIntegrityToken): IntegrityResult;
56
+ export declare function checkGetUserMediaIntegrity(options?: IntegrityCheckOptions): IntegrityResult;
25
57
  /**
26
- * Lightweight pre-call guard (Layer 1 + Layer 3 only, no iframe).
27
- * Returns `true` if tampering is detected.
58
+ * Lightweight pre-call guard. Returns `true` if tampering is detected.
59
+ * Returns `false` immediately when not enabled.
60
+ *
61
+ * Runs Layer 1 (corroborated by a cached Layer 2 verdict) and Layer 3.
62
+ * The full check at mount time (`checkGetUserMediaIntegrity`) re-runs Layer 2
63
+ * fresh for completeness; this guard uses the cache so per-call cost is low.
64
+ *
65
+ * For strong tamper resistance, customers should pass a token captured via
66
+ * `captureMediaIntegrity` — Layer 1 is best-effort and can produce false
67
+ * positives against legitimate post-init shims (`webrtc-adapter`, polyfills,
68
+ * browser extensions).
28
69
  */
29
- export declare function guardGetUserMedia(token?: MediaIntegrityToken): boolean;
70
+ export declare function guardGetUserMedia(options?: IntegrityCheckOptions): boolean;
30
71
  export {};
31
72
  //# sourceMappingURL=getUserMediaIntegrity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"getUserMediaIntegrity.d.ts","sourceRoot":"","sources":["../../../src/lib/camera/getUserMediaIntegrity.ts"],"names":[],"mappings":"AAcA,OAAO,CAAC,MAAM,wBAAwB,EAAE,OAAO,MAAM,CAAA;AAErD,iFAAiF;AACjF,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,CAAC,wBAAwB,CAAC,EAAE,IAAI,CAAA;CAC1C,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,OAAO,CAAA;IACjB,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB,CAAA;AAYD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,IAAI,mBAAmB,CAS3D;AAqJD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,CAAC,EAAE,mBAAmB,GAC1B,eAAe,CAqBjB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,CAAC,EAAE,mBAAmB,GAAG,OAAO,CActE"}
1
+ {"version":3,"file":"getUserMediaIntegrity.d.ts","sourceRoot":"","sources":["../../../src/lib/camera/getUserMediaIntegrity.ts"],"names":[],"mappings":"AAcA,OAAO,CAAC,MAAM,wBAAwB,EAAE,OAAO,MAAM,CAAA;AAErD,iFAAiF;AACjF,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,CAAC,wBAAwB,CAAC,EAAE,IAAI,CAAA;CAC1C,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,OAAO,CAAA;IACjB,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB,CAAA;AA+BD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,qBAAqB,IAAI,mBAAmB,CAS3D;AAsLD,MAAM,MAAM,qBAAqB,GAAG;IAClC,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,oDAAoD;IACpD,KAAK,CAAC,EAAE,mBAAmB,CAAA;CAC5B,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,GAAE,qBAA0B,GAClC,eAAe,CAwBjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAiBT"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=getUserMediaIntegrity.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getUserMediaIntegrity.test.d.ts","sourceRoot":"","sources":["../../../src/lib/camera/getUserMediaIntegrity.test.ts"],"names":[],"mappings":""}
@@ -235,7 +235,7 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
235
235
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
236
236
  };
237
237
 
238
- var webSdkVersion = '2.3.212';
238
+ var webSdkVersion = '2.3.213';
239
239
 
240
240
  function getPlatform() {
241
241
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -4194,6 +4194,24 @@ var LOG_TAG$2 = 'camera:getUserMediaIntegrity';
4194
4194
  // Module-level boot-time cached references (SSR-safe)
4195
4195
  var _createElement = typeof document !== 'undefined' ? Document.prototype.createElement : undefined;
4196
4196
  var _getUserMedia = typeof navigator !== 'undefined' ? (_a = navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.getUserMedia : undefined;
4197
+ // Cached Layer 2 verdict — Layer 2 creates an iframe (expensive). Cache the
4198
+ // result for the lifetime of the page so repeated guard() calls are cheap.
4199
+ // Keyed by the current navigator.mediaDevices.getUserMedia identity so a
4200
+ // post-init replacement re-runs Layer 2 once and the new verdict sticks.
4201
+ var _cachedLayer2;
4202
+ function getCachedLayer2Verdict() {
4203
+ var _a;
4204
+ var currentSource = typeof navigator !== 'undefined' ? (_a = navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.getUserMedia : undefined;
4205
+ if (_cachedLayer2 && _cachedLayer2.source === currentSource) {
4206
+ return _cachedLayer2.verdict;
4207
+ }
4208
+ var verdict = checkLayer2();
4209
+ _cachedLayer2 = {
4210
+ source: currentSource,
4211
+ verdict: verdict
4212
+ };
4213
+ return verdict;
4214
+ }
4197
4215
  // --- Layer 3: Customer-provided token ---
4198
4216
  var tokenStore = new WeakMap();
4199
4217
  /**
@@ -4201,7 +4219,25 @@ var tokenStore = new WeakMap();
4201
4219
  * Customers should call this as early as possible in their application boot,
4202
4220
  * before any third-party scripts have a chance to monkey-patch browser APIs.
4203
4221
  *
4204
- * The returned token is passed to SDK components via the `mediaIntegrityToken` prop.
4222
+ * The returned token is passed to SDK components via the `mediaIntegrityToken`
4223
+ * prop. **Passing a token is the recommended way to enable strong tamper
4224
+ * detection.** Without it, the SDK falls back to Layer 1 (boot-time reference
4225
+ * snapshot) and Layer 2 (page-vs-iframe `toString` heuristic), both of which
4226
+ * are best-effort and can produce false positives — e.g. legitimate post-init
4227
+ * shims like `webrtc-adapter`, browser-level instrumentation in Chrome for
4228
+ * iOS (CriOS), and some browser extensions all replace `getUserMedia` in ways
4229
+ * that look indistinguishable from tampering at those layers.
4230
+ *
4231
+ * Layer 3 (this token) compares against a snapshot the customer captures at
4232
+ * a moment of their choosing, so it is robust against post-capture tampering
4233
+ * regardless of how sophisticated the attacker is at faking `[native code]`
4234
+ * after the snapshot — but it cannot defend against tampering that already
4235
+ * happened before `captureMediaIntegrity` ran. Capture early.
4236
+ *
4237
+ * **Must be called in a browser context** (`navigator.mediaDevices` available).
4238
+ * Calling during SSR / pre-DOM produces a token whose snapshot is empty;
4239
+ * subsequent integrity checks against such a token will report "unrecognized
4240
+ * or forged token" — a false positive caused by capture-time misuse.
4205
4241
  */
4206
4242
  function captureMediaIntegrity() {
4207
4243
  var token = Object.freeze({
@@ -4215,8 +4251,8 @@ function captureMediaIntegrity() {
4215
4251
  }
4216
4252
  return token;
4217
4253
  }
4218
- // --- Layer 1: Boot-time referential equality ---
4219
- function checkLayer1() {
4254
+ // --- Layer 1: Boot-time referential equality (with Layer 2 corroboration) ---
4255
+ function checkLayer1(layer2) {
4220
4256
  var details = [];
4221
4257
  // SSR or missing mediaDevices — pass gracefully
4222
4258
  if (!_getUserMedia || typeof navigator === 'undefined' || !navigator.mediaDevices) {
@@ -4225,8 +4261,19 @@ function checkLayer1() {
4225
4261
  details: details
4226
4262
  };
4227
4263
  }
4228
- if (navigator.mediaDevices.getUserMedia !== _getUserMedia) {
4229
- details.push('Layer 1: navigator.mediaDevices.getUserMedia reference differs from boot-time snapshot');
4264
+ if (navigator.mediaDevices.getUserMedia === _getUserMedia) {
4265
+ return {
4266
+ tampered: false,
4267
+ details: details
4268
+ };
4269
+ }
4270
+ // Reference differs from boot snapshot. This may be a legitimate post-init
4271
+ // shim (webrtc-adapter, polyfill, browser extension). Only flag when Layer 2
4272
+ // gives positive evidence of tampering. If Layer 2 is unavailable (no
4273
+ // document) or itself reports clean, defer to Layer 2's signal and don't
4274
+ // double-report at Layer 1.
4275
+ if (layer2 === null || layer2 === void 0 ? void 0 : layer2.tampered) {
4276
+ details.push('Layer 1: navigator.mediaDevices.getUserMedia reference differs from boot-time snapshot (corroborated by Layer 2)');
4230
4277
  }
4231
4278
  return {
4232
4279
  tampered: details.length > 0,
@@ -4235,7 +4282,7 @@ function checkLayer1() {
4235
4282
  }
4236
4283
  // --- Layer 2: Fresh iframe cross-context toString ---
4237
4284
  function checkLayer2() {
4238
- var _a, _b;
4285
+ var _a, _b, _c, _d;
4239
4286
  var details = [];
4240
4287
  // SSR or missing prerequisites — pass gracefully
4241
4288
  if (typeof document === 'undefined' || !_createElement || !navigator.mediaDevices) {
@@ -4281,8 +4328,24 @@ function checkLayer2() {
4281
4328
  // Neither is native — something has tampered at a deep level
4282
4329
  details.push('Layer 2: neither page nor iframe getUserMedia appear native');
4283
4330
  } else if (pageIsNative && !iframeIsNative) {
4284
- // Page claims native but iframe disagrees suspicious
4285
- details.push('Layer 2: page getUserMedia claims native but iframe does not');
4331
+ // Iframe disagrees with page about native-ness. Probe iframe
4332
+ // trustworthiness via another mediaDevices method before deciding
4333
+ // whether to flag. Browsers (Chrome for iOS / CriOS) and some
4334
+ // extensions wrap iframe getUserMedia specifically while leaving
4335
+ // sibling methods intact; broadly-tampered iframes also can't be
4336
+ // trusted as a "what does native look like" reference. In neither
4337
+ // case is the iframe a reliable witness, so we trust the page-
4338
+ // level [native code] signal and don't flag here.
4339
+ //
4340
+ // The strong defense against a faked-native page-level impostor
4341
+ // is Layer 3 (customer-captured token), not Layer 2 heuristics.
4342
+ var iframeEnumerateDevices = (_d = (_c = iframeWindow.navigator) === null || _c === void 0 ? void 0 : _c.mediaDevices) === null || _d === void 0 ? void 0 : _d.enumerateDevices;
4343
+ var iframeEnumerateNative = iframeEnumerateDevices ? String(iframeToString.call(iframeEnumerateDevices)).includes('[native code]') : false;
4344
+ if (iframeEnumerateNative) {
4345
+ debug("".concat(LOG_TAG$2, " Layer 2: page getUserMedia native; iframe getUserMedia wrapped but iframe enumerateDevices native \u2014 browser-level instrumentation pattern (e.g. CriOS), not flagged"));
4346
+ } else {
4347
+ debug("".concat(LOG_TAG$2, " Layer 2: page getUserMedia native; iframe broadly unreliable as a reference (enumerateDevices also non-native or unavailable), not flagged"));
4348
+ }
4286
4349
  }
4287
4350
  // pageIsNative=false, iframeIsNative=true → legitimate shim (e.g. adapter.js), not flagged
4288
4351
  // both native → clean, not flagged
@@ -4343,20 +4406,36 @@ function checkLayer3(token) {
4343
4406
  details: details
4344
4407
  };
4345
4408
  }
4346
- // --- Public API ---
4347
4409
  /**
4348
4410
  * Run all applicable integrity check layers.
4349
- * Layer 1: Boot-time referential equality
4350
- * Layer 2: Fresh iframe cross-context toString (async-safe but sync)
4351
- * Layer 3: Customer-provided token validation (if token supplied)
4411
+ *
4412
+ * - **Layer 1**: Boot-time referential equality (corroborated by Layer 2).
4413
+ * Best-effort; misses attackers who inject before SDK load.
4414
+ * - **Layer 2**: Fresh-iframe cross-realm `toString` comparison. Best-effort;
4415
+ * produces false positives in browser-level instrumentation contexts (CriOS,
4416
+ * extensions). The page-vs-iframe disagreement case is gated on iframe
4417
+ * trustworthiness to mitigate this.
4418
+ * - **Layer 3**: Customer-provided token validation (only runs when a token
4419
+ * is supplied). **This is the strong defense** — see `captureMediaIntegrity`.
4420
+ *
4421
+ * Returns clean immediately if `enabled` is not true.
4352
4422
  */
4353
- function checkGetUserMediaIntegrity(token) {
4423
+ function checkGetUserMediaIntegrity(options) {
4424
+ if (options === void 0) {
4425
+ options = {};
4426
+ }
4427
+ if (!options.enabled) {
4428
+ return {
4429
+ tampered: false,
4430
+ details: []
4431
+ };
4432
+ }
4354
4433
  var allDetails = [];
4355
- var l1 = checkLayer1();
4356
- allDetails.push.apply(allDetails, l1.details);
4357
4434
  var l2 = checkLayer2();
4435
+ var l1 = checkLayer1(l2);
4436
+ allDetails.push.apply(allDetails, l1.details);
4358
4437
  allDetails.push.apply(allDetails, l2.details);
4359
- var l3 = checkLayer3(token);
4438
+ var l3 = checkLayer3(options.token);
4360
4439
  allDetails.push.apply(allDetails, l3.details);
4361
4440
  var tampered = l1.tampered || l2.tampered || l3.tampered;
4362
4441
  if (tampered) {
@@ -4370,12 +4449,26 @@ function checkGetUserMediaIntegrity(token) {
4370
4449
  };
4371
4450
  }
4372
4451
  /**
4373
- * Lightweight pre-call guard (Layer 1 + Layer 3 only, no iframe).
4374
- * Returns `true` if tampering is detected.
4452
+ * Lightweight pre-call guard. Returns `true` if tampering is detected.
4453
+ * Returns `false` immediately when not enabled.
4454
+ *
4455
+ * Runs Layer 1 (corroborated by a cached Layer 2 verdict) and Layer 3.
4456
+ * The full check at mount time (`checkGetUserMediaIntegrity`) re-runs Layer 2
4457
+ * fresh for completeness; this guard uses the cache so per-call cost is low.
4458
+ *
4459
+ * For strong tamper resistance, customers should pass a token captured via
4460
+ * `captureMediaIntegrity` — Layer 1 is best-effort and can produce false
4461
+ * positives against legitimate post-init shims (`webrtc-adapter`, polyfills,
4462
+ * browser extensions).
4375
4463
  */
4376
- function guardGetUserMedia(token) {
4377
- var l1 = checkLayer1();
4378
- var l3 = checkLayer3(token);
4464
+ function guardGetUserMedia(options) {
4465
+ if (options === void 0) {
4466
+ options = {};
4467
+ }
4468
+ if (!options.enabled) return false;
4469
+ var l2 = getCachedLayer2Verdict();
4470
+ var l1 = checkLayer1(l2);
4471
+ var l3 = checkLayer3(options.token);
4379
4472
  var tampered = l1.tampered || l3.tampered;
4380
4473
  if (tampered) {
4381
4474
  error("".concat(LOG_TAG$2, " guard detected tampering:"), __spreadArray(__spreadArray([], l1.details, true), l3.details, true));
@@ -4385,16 +4478,19 @@ function guardGetUserMedia(token) {
4385
4478
 
4386
4479
  var LOG_TAG$1 = 'camera:Camera';
4387
4480
  function listAvailableCameras(facingMode_1) {
4388
- return __awaiter(this, arguments, void 0, function (facingMode, requestMicAccess, token) {
4481
+ return __awaiter(this, arguments, void 0, function (facingMode, requestMicAccess, tamper) {
4389
4482
  var cameraEnumerationStream, allDevices, allowedVideoDevices;
4390
4483
  if (requestMicAccess === void 0) {
4391
4484
  requestMicAccess = false;
4392
4485
  }
4486
+ if (tamper === void 0) {
4487
+ tamper = {};
4488
+ }
4393
4489
  return __generator(this, function (_a) {
4394
4490
  switch (_a.label) {
4395
4491
  case 0:
4396
4492
  // The first thing we need to do is call getUserMedia() so that the subsequent call to enumerateDevices() works.
4397
- if (guardGetUserMedia(token)) {
4493
+ if (guardGetUserMedia(tamper)) {
4398
4494
  throw new Error('getUserMedia tampering detected');
4399
4495
  }
4400
4496
  return [4 /*yield*/, navigator.mediaDevices.getUserMedia({
@@ -5732,7 +5828,10 @@ var createCameraStore = function createCameraStore(config) {
5732
5828
  case 0:
5733
5829
  debug("".concat(LOG_TAG, " requestCameraAccess"), new Error().stack);
5734
5830
  _a = get(), videoRef = _a.videoRef, releaseCameraAccess = _a.releaseCameraAccess, preferFrontFacingCamera = _a.preferFrontFacingCamera, preferIphoneContinuityCamera = _a.preferIphoneContinuityCamera, iphoneContinuityCameraDenied = _a.iphoneContinuityCameraDenied, enableTamperDetection = _a.enableTamperDetection, mediaIntegrityToken = _a.mediaIntegrityToken;
5735
- if (enableTamperDetection && guardGetUserMedia(mediaIntegrityToken)) {
5831
+ if (guardGetUserMedia({
5832
+ enabled: enableTamperDetection,
5833
+ token: mediaIntegrityToken
5834
+ })) {
5736
5835
  set({
5737
5836
  cameraTamperingDetected: true
5738
5837
  });
@@ -5742,7 +5841,10 @@ var createCameraStore = function createCameraStore(config) {
5742
5841
  _f.label = 1;
5743
5842
  case 1:
5744
5843
  _f.trys.push([1, 11,, 12]);
5745
- return [4 /*yield*/, listAvailableCameras(undefined, false, mediaIntegrityToken)];
5844
+ return [4 /*yield*/, listAvailableCameras(undefined, false, {
5845
+ enabled: enableTamperDetection,
5846
+ token: mediaIntegrityToken
5847
+ })];
5746
5848
  case 2:
5747
5849
  availableCameras = _f.sent();
5748
5850
  selectedCamera = void 0;
@@ -5954,7 +6056,10 @@ var createCameraStore = function createCameraStore(config) {
5954
6056
  switch (_a.label) {
5955
6057
  case 0:
5956
6058
  get().releaseMicrophoneAccess();
5957
- if (get().enableTamperDetection && guardGetUserMedia(get().mediaIntegrityToken)) {
6059
+ if (guardGetUserMedia({
6060
+ enabled: get().enableTamperDetection,
6061
+ token: get().mediaIntegrityToken
6062
+ })) {
5958
6063
  set({
5959
6064
  cameraTamperingDetected: true
5960
6065
  });
@@ -6078,8 +6183,10 @@ function CameraStoreProvider(_a) {
6078
6183
  }));
6079
6184
  React.useEffect(function () {
6080
6185
  var _a;
6081
- if (!enableTamperDetection) return;
6082
- var result = checkGetUserMediaIntegrity(mediaIntegrityToken);
6186
+ var result = checkGetUserMediaIntegrity({
6187
+ enabled: enableTamperDetection,
6188
+ token: mediaIntegrityToken
6189
+ });
6083
6190
  if (result.tampered) {
6084
6191
  (_a = store.current) === null || _a === void 0 ? void 0 : _a.setState({
6085
6192
  cameraTamperingDetected: true