@ozura/elements 1.2.4-next.54 → 1.2.4-next.56

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.
@@ -216,11 +216,24 @@ const OZ_ERROR_CODES = new Set(['network', 'timeout', 'auth', 'validation', 'ser
216
216
  function isOzErrorCode(value) {
217
217
  return typeof value === 'string' && OZ_ERROR_CODES.has(value);
218
218
  }
219
+ /**
220
+ * Strips PAN-shaped digit sequences from raw vault / Pay API error strings
221
+ * before they are stored on OzError.raw.
222
+ *
223
+ * The vault and Pay API should never echo card data in error messages — but
224
+ * this is a defense-in-depth layer. 13–19 digit runs (optionally separated
225
+ * by spaces or dashes) match every major card number format. Shorter digit
226
+ * runs (CVV, ZIP, HTTP status codes) are left untouched.
227
+ */
228
+ const RAW_PAN_RE = /\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{1,7}\b|\b\d{13,19}\b/g;
229
+ function redactRawString(s) {
230
+ return s.replace(RAW_PAN_RE, '[REDACTED]');
231
+ }
219
232
  class OzError extends Error {
220
233
  constructor(message, raw, errorCode) {
221
234
  super(message);
222
235
  this.name = 'OzError';
223
- this.raw = raw !== null && raw !== void 0 ? raw : message;
236
+ this.raw = redactRawString(raw !== null && raw !== void 0 ? raw : message);
224
237
  this.errorCode = errorCode !== null && errorCode !== void 0 ? errorCode : 'unknown';
225
238
  this.retryable = this.errorCode === 'network' || this.errorCode === 'timeout' || this.errorCode === 'server';
226
239
  }
@@ -417,17 +430,26 @@ class OzElement {
417
430
  accountNumber: 'account number',
418
431
  routingNumber: 'routing number',
419
432
  }[this.elementType]) !== null && _a !== void 0 ? _a : this.elementType} input`;
420
- // sandbox="allow-scripts" gives correct iframe isolation:
421
- // - Scripts run (allow-scripts), so the field JS executes normally.
422
- // - NO allow-same-origin: the frame cannot access window.parent's DOM,
423
- // localStorage, or cookies — prevents sandbox escape even if served
424
- // from the same origin.
425
- // - NO allow-top-navigation: a rogue/compromised element frame cannot
426
- // navigate window.top (clickjacking prevention).
427
- // - NO allow-forms / allow-popups: reduces attack surface.
428
- // Field values are delivered via postMessage, so no parent access is
429
- // needed allow-scripts alone is sufficient.
430
- iframe.setAttribute('sandbox', 'allow-scripts');
433
+ // sandbox="allow-scripts allow-same-origin" gives correct iframe isolation:
434
+ // - allow-scripts: JS runs, so the field JS executes normally.
435
+ // - allow-same-origin: the frame keeps its actual origin (elements.ozura.com
436
+ // in production) so that:
437
+ // (a) window.parent.postMessage() carries a real origin that OzVault can
438
+ // validate (without this the frame gets a null/opaque origin and every
439
+ // OZ_FRAME_READY message is silently dropped by the origin check), and
440
+ // (b) OzVault can deliver OZ_INIT back to the frame (postMessage to a
441
+ // null-origin target is never delivered).
442
+ // - In PRODUCTION the frames are served from elements.ozura.com and embedded
443
+ // on a different merchant domain — Same-Origin Policy already prevents the
444
+ // frame from accessing window.parent.document or merchant cookies, making
445
+ // allow-same-origin a no-op from a security perspective.
446
+ // - In LOCAL DEV (localhost) both parent and frames share the same origin;
447
+ // allow-same-origin alongside allow-scripts does technically weaken sandbox
448
+ // isolation, but this is a local dev server only — not a production risk.
449
+ // NOT included: allow-top-navigation, allow-popups, allow-forms — prevents
450
+ // a compromised element frame from navigating the merchant page or opening
451
+ // popups even if the CDN bundle were somehow replaced.
452
+ iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
431
453
  // Use hash instead of query string — survives clean-URL redirects from static servers.
432
454
  // parentOrigin lets the frame target postMessage to the merchant origin instead of '*'.
433
455
  const parentOrigin = typeof window !== 'undefined' ? window.location.origin : '';