@anonympins/fingerprint 0.7.4 → 0.7.5

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.
@@ -412,54 +412,80 @@ const ClientLibrary = {
412
412
  },
413
413
 
414
414
  /**
415
- * Injects invisible phantom interactive elements to trap bots (focus/hover).
415
+ * Injects invisible phantom interactive elements and forms within a closed Shadow DOM container to trap bots (focus/hover/click).
416
416
  */
417
417
  injectPhantomTraps() {
418
- if (typeof document === 'undefined') return;
418
+ if (typeof document === 'undefined' || !document.body) return;
419
+
420
+ const host = document.createElement('div');
421
+ host.setAttribute('aria-hidden', 'true');
422
+ host.style.position = 'absolute';
423
+ host.style.left = '-9999px';
424
+ host.style.top = '-9999px';
425
+ host.style.width = '0';
426
+ host.style.height = '0';
427
+ host.style.overflow = 'hidden';
428
+
429
+ const shadow = typeof host.attachShadow === 'function'
430
+ ? host.attachShadow({ mode: 'closed' })
431
+ : host;
432
+
433
+ const style = document.createElement('style');
434
+ style.textContent = `
435
+ :host {
436
+ position: absolute;
437
+ left: -9999px;
438
+ top: -9999px;
439
+ width: 0;
440
+ height: 0;
441
+ overflow: hidden;
442
+ }
443
+ a, input, button, form {
444
+ opacity: 0.001;
445
+ pointer-events: auto;
446
+ }
447
+ `;
448
+ shadow.appendChild(style);
419
449
 
420
- // Create a phantom interactive element
450
+ const triggerTrap = () => {
451
+ this.onHoneypotTrigger();
452
+ };
453
+
454
+ // 1. Phantom interactive link
421
455
  const phantom = document.createElement('a');
422
456
  phantom.href = '#';
423
457
  // Random deceptive name to attract automated link/form parsers
424
458
  const phantomNames = ['sys-session-recovery', 'auth-token-refresh', 'debug-console-login', 'admin-portal-access', 'security-bypass-bypass', 'recovery-key-session', 'api-key-test', 'client-secrets-access'];
425
459
  phantom.id = phantomNames[Math.floor(secureRandom() * phantomNames.length)] + '-' + genRandStr(6);
426
460
  phantom.className = genRandStr(8);
427
- phantom.tabIndex = 0; // In natural tab flow
428
- phantom.setAttribute('aria-hidden', 'true'); // Hidden from legitimate screen readers
429
-
430
- // Invisible yet interactive style (1px x 1px, nearly transparent)
431
- phantom.style.position = 'fixed';
432
- phantom.style.top = '1px';
433
- phantom.style.left = '1px';
434
- phantom.style.width = '1px';
435
- phantom.style.height = '1px';
436
- phantom.style.opacity = '0.001';
437
- phantom.style.zIndex = '99999';
438
- phantom.style.overflow = 'hidden';
439
- phantom.style.pointerEvents = 'auto';
440
-
441
- const triggerTrap = () => {
442
- this.onHoneypotTrigger();
443
- };
444
-
461
+ phantom.tabIndex = 0; // In natural tab flow for crawler parsers
445
462
  phantom.addEventListener('focus', triggerTrap, { passive: true });
446
463
  phantom.addEventListener('mouseover', triggerTrap, { passive: true });
447
-
448
- // Polymorphic DOM insertion of the phantom trap
449
- const nestingOptions = [
450
- () => document.body.appendChild(phantom),
451
- () => {
452
- const wrapper = document.createElement(secureRandom() > 0.5 ? 'span' : 'div');
453
- wrapper.className = genRandStr(8);
454
- wrapper.style.position = 'absolute';
455
- wrapper.style.width = '0';
456
- wrapper.style.height = '0';
457
- wrapper.style.overflow = 'hidden';
458
- wrapper.appendChild(phantom);
459
- document.body.appendChild(wrapper);
460
- }
461
- ];
462
- nestingOptions[Math.floor(secureRandom() * nestingOptions.length)]();
464
+ phantom.addEventListener('click', (e) => {
465
+ if (e && typeof e.preventDefault === 'function') e.preventDefault();
466
+ triggerTrap();
467
+ }, { passive: false });
468
+
469
+ // 2. Deceptive hidden form with bait input
470
+ const phantomForm = document.createElement('form');
471
+ phantomForm.action = '#';
472
+ phantomForm.tabIndex = -1;
473
+ const inputNames = ['session_token', 'admin_pwd', 'secret_key', 'auth_bypass'];
474
+ const phantomInput = document.createElement('input');
475
+ phantomInput.type = 'text';
476
+ phantomInput.name = inputNames[Math.floor(secureRandom() * inputNames.length)] + '_' + genRandStr(4);
477
+ phantomInput.tabIndex = 0;
478
+ phantomInput.autocomplete = 'off';
479
+ phantomInput.addEventListener('focus', triggerTrap, { passive: true });
480
+ phantomInput.addEventListener('input', triggerTrap, { passive: true });
481
+ phantomInput.addEventListener('click', triggerTrap, { passive: true });
482
+ phantomInput.addEventListener('change', triggerTrap, { passive: true });
483
+
484
+ phantomForm.appendChild(phantomInput);
485
+ shadow.appendChild(phantom);
486
+ shadow.appendChild(phantomForm);
487
+
488
+ document.body.appendChild(host);
463
489
  },
464
490
 
465
491
  /**
@@ -800,7 +826,7 @@ const ClientLibrary = {
800
826
  });
801
827
 
802
828
  // 3. Generate trap inputs inside a closed Shadow DOM
803
- if (typeof document !== 'undefined' && honeypotFieldNames.length > 0) {
829
+ if (typeof document !== 'undefined' && honeypotFieldNames.length > 0 && document.body) {
804
830
  const host = document.createElement('div');
805
831
  host.setAttribute('aria-hidden', 'true');
806
832
  host.style.position = 'absolute';
@@ -808,7 +834,9 @@ const ClientLibrary = {
808
834
  host.style.height = '0';
809
835
  host.style.overflow = 'hidden';
810
836
 
811
- const shadow = host.attachShadow({ mode: 'closed' });
837
+ const shadow = typeof host.attachShadow === 'function'
838
+ ? host.attachShadow({ mode: 'closed' })
839
+ : host;
812
840
 
813
841
  // Randomize classes, CSS variables, and layout tags
814
842
  const wrapperClass = genRandStr(10);
@@ -858,6 +886,7 @@ const ClientLibrary = {
858
886
  input.addEventListener('input', trigger, { passive: true });
859
887
  input.addEventListener('change', trigger, { passive: true });
860
888
  input.addEventListener('focus', trigger, { passive: true });
889
+ input.addEventListener('click', trigger, { passive: true });
861
890
 
862
891
  // Polymorphic nesting of label and input
863
892
  const nestingType = Math.floor(secureRandom() * 3);
@@ -1255,7 +1284,7 @@ const ClientLibrary = {
1255
1284
  * @private
1256
1285
  */
1257
1286
  injectTrapLinks(urls) {
1258
- if (!urls || urls.length === 0 || typeof document === 'undefined') {
1287
+ if (!urls || urls.length === 0 || typeof document === 'undefined' || !document.body) {
1259
1288
  return;
1260
1289
  }
1261
1290
 
@@ -1266,7 +1295,9 @@ const ClientLibrary = {
1266
1295
  host.style.height = '0';
1267
1296
  host.style.overflow = 'hidden';
1268
1297
 
1269
- const shadow = host.attachShadow({ mode: 'closed' });
1298
+ const shadow = typeof host.attachShadow === 'function'
1299
+ ? host.attachShadow({ mode: 'closed' })
1300
+ : host;
1270
1301
 
1271
1302
  // Randomize classes, CSS variables, and layout tags
1272
1303
  const wrapperClass = genRandStr(10);
@@ -1330,10 +1361,13 @@ const ClientLibrary = {
1330
1361
  link.innerHTML = `<span>&gt; ${i + 1}</span>`;
1331
1362
  }
1332
1363
 
1333
- const trigger = () => {
1364
+ const trigger = (e) => {
1365
+ if (e && typeof e.preventDefault === 'function') {
1366
+ e.preventDefault();
1367
+ }
1334
1368
  this.onHoneypotTrigger();
1335
1369
  };
1336
- link.addEventListener('click', trigger, { passive: true });
1370
+ link.addEventListener('click', trigger, { passive: false });
1337
1371
  link.addEventListener('focus', trigger, { passive: true });
1338
1372
  link.addEventListener('mouseover', trigger, { passive: true });
1339
1373