@anyreplay/browser 0.2.0 → 0.2.1

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.
package/dist/index.js CHANGED
@@ -3815,10 +3815,12 @@ var AssetCollector = class {
3815
3815
  body: JSON.stringify(body)
3816
3816
  });
3817
3817
  const known = await post("/v1/ingest/assets/known", { projectKey, hashes: [sha256], ...app });
3818
- if (known.ok) {
3819
- const body = await known.json();
3820
- if (Array.isArray(body.known) && body.known.includes(sha256)) return true;
3818
+ if (!known.ok) {
3819
+ if (known.status === 401 || known.status === 403) this.stop();
3820
+ return false;
3821
3821
  }
3822
+ const answer = await known.json();
3823
+ if (Array.isArray(answer.known) && answer.known.includes(sha256)) return true;
3822
3824
  const upload = await post("/v1/ingest/assets", { projectKey, sha256, data: toBase64(bytes), ...app });
3823
3825
  return upload.ok;
3824
3826
  }
@@ -4123,6 +4125,13 @@ function looksLikeCardNumber(text) {
4123
4125
  }
4124
4126
  return sum % 10 === 0;
4125
4127
  }
4128
+ function mayBecomeCardNumber(text) {
4129
+ if (!/^[2-6][0-9 -]*$/.test(text)) return false;
4130
+ const groups = text.split(/[ -]+/);
4131
+ if (groups.slice(0, -1).some((group) => group.length < 4)) return false;
4132
+ const digits = groups.join("").length;
4133
+ return digits > 6 && digits <= 19;
4134
+ }
4126
4135
  function isMarkedByCustomer(node, maskClass) {
4127
4136
  var _a;
4128
4137
  let element = asElement(node);
@@ -4137,8 +4146,19 @@ function shouldMaskValue(text, node, policy) {
4137
4146
  if (policy.maskEveryField) return true;
4138
4147
  if (isSensitiveField(node)) return true;
4139
4148
  if (isMarkedByCustomer(node, policy.maskClass)) return true;
4140
- return looksLikeCardNumber(text);
4149
+ return cardShaped(text);
4150
+ }
4151
+ var cardShaped = (text) => looksLikeCardNumber(text) || mayBecomeCardNumber(text);
4152
+ var EDITABLE = '[contenteditable]:not([contenteditable="false"])';
4153
+ function insideEditable(node) {
4154
+ var _a;
4155
+ const live = node;
4156
+ const element = (live == null ? void 0 : live.nodeType) === 3 ? (_a = live.parentElement) != null ? _a : null : asElement(live);
4157
+ return typeof (element == null ? void 0 : element.closest) === "function" && element.closest(EDITABLE) !== null;
4141
4158
  }
4159
+ var isEditableSerialised = (attributes) => attributes.contenteditable !== void 0 && attributes.contenteditable !== "false";
4160
+ var typedCardShaped = (text) => cardShaped(text.replace(/\u00a0/g, " ").trim());
4161
+ var maskText = (text) => text.replace(/\S/g, "*");
4142
4162
  var MUTATION = 0;
4143
4163
  var INPUT = 5;
4144
4164
  var ELEMENT_NODE = 2;
@@ -4153,23 +4173,27 @@ function maskTextChildren(node) {
4153
4173
  maskTextChildren(child);
4154
4174
  }
4155
4175
  }
4156
- function scrubTree(node, policy, masked) {
4176
+ function scrubTree(node, policy, masked, editable = false) {
4157
4177
  var _a, _b;
4158
4178
  if (!node) return;
4159
4179
  const attributes = (_a = node.attributes) != null ? _a : {};
4160
4180
  const inheritedMask = masked || hasClass(attributes, policy.maskClass);
4181
+ const inheritedEditable = editable || node.type === ELEMENT_NODE && isEditableSerialised(attributes);
4182
+ if (editable && node.type === TEXT_NODE && typeof node.textContent === "string" && typedCardShaped(node.textContent)) {
4183
+ node.textContent = maskText(node.textContent);
4184
+ }
4161
4185
  if (node.type === ELEMENT_NODE && node.tagName && FIELD_TAGS.has(node.tagName.toLowerCase())) {
4162
4186
  const value = attributes.value;
4163
- const shouldMask = policy.maskEveryField || inheritedMask || isSensitiveSerialised(attributes) || typeof value === "string" && looksLikeCardNumber(value);
4187
+ const shouldMask = policy.maskEveryField || inheritedMask || isSensitiveSerialised(attributes) || typeof value === "string" && cardShaped(value);
4164
4188
  if (shouldMask) {
4165
4189
  if (typeof value === "string" && value !== "") attributes.value = maskValue(value);
4166
4190
  if (node.tagName.toLowerCase() === "textarea") maskTextChildren(node);
4167
4191
  }
4168
4192
  }
4169
- for (const child of (_b = node.childNodes) != null ? _b : []) scrubTree(child, policy, inheritedMask);
4193
+ for (const child of (_b = node.childNodes) != null ? _b : []) scrubTree(child, policy, inheritedMask, inheritedEditable);
4170
4194
  }
4171
4195
  function scrubEvent(event, getNode, policy) {
4172
- var _a, _b, _c, _d, _e;
4196
+ var _a, _b, _c, _d, _e, _f;
4173
4197
  if (!event.data) return;
4174
4198
  if (event.type === 2) {
4175
4199
  scrubTree(event.data.node, policy, false);
@@ -4194,7 +4218,11 @@ function scrubEvent(event, getNode, policy) {
4194
4218
  }
4195
4219
  for (const add of (_e = data.adds) != null ? _e : []) {
4196
4220
  const parent = typeof (add == null ? void 0 : add.parentId) === "number" ? getNode(add.parentId) : null;
4197
- scrubTree(add == null ? void 0 : add.node, policy, isMarkedByCustomer(parent, policy.maskClass));
4221
+ scrubTree(add == null ? void 0 : add.node, policy, isMarkedByCustomer(parent, policy.maskClass), insideEditable(parent));
4222
+ }
4223
+ for (const change of (_f = data.texts) != null ? _f : []) {
4224
+ if (typeof (change == null ? void 0 : change.value) !== "string" || !typedCardShaped(change.value)) continue;
4225
+ if (typeof change.id === "number" && insideEditable(getNode(change.id))) change.value = maskText(change.value);
4198
4226
  }
4199
4227
  }
4200
4228
 
@@ -5000,7 +5028,7 @@ var Transport = class {
5000
5028
 
5001
5029
  // src/version.ts
5002
5030
  var SDK_NAME = "@anyreplay/browser";
5003
- var SDK_VERSION = true ? "0.2.0" : "0.0.0-dev";
5031
+ var SDK_VERSION = true ? "0.2.1" : "0.0.0-dev";
5004
5032
  var PLATFORM = "web";
5005
5033
 
5006
5034
  // src/visitor.ts
@@ -5107,6 +5135,8 @@ function forgetVisitor(local, session) {
5107
5135
  }
5108
5136
 
5109
5137
  // src/recorder.ts
5138
+ var RRWEB_DOM_CONTENT_LOADED = 0;
5139
+ var RRWEB_LOAD = 1;
5110
5140
  var RAGE_CLICK_COUNT = 3;
5111
5141
  var RAGE_CLICK_WINDOW_MS = 1e3;
5112
5142
  var RAGE_CLICK_RADIUS_PX = 30;
@@ -5304,6 +5334,7 @@ function createRecorder(rawOptions, shell) {
5304
5334
  stopRecording = record({
5305
5335
  emit: (event) => {
5306
5336
  const typed = event;
5337
+ if (typed.type === RRWEB_DOM_CONTENT_LOADED || typed.type === RRWEB_LOAD) return;
5307
5338
  scrubEvent(typed, (id) => record.mirror.getNode(id), policy);
5308
5339
  assets == null ? void 0 : assets.scan(typed);
5309
5340
  noteInteraction(typed, channel);