@fanboynz/network-scanner 2.0.12 → 2.0.14

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.
@@ -399,6 +399,10 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
399
399
  const automationProps = [
400
400
  'callPhantom', '_phantom', '__nightmare', '_selenium', '__selenium_unwrapped',
401
401
  '__webdriver_evaluate', '__driver_evaluate', '__webdriver_script_function',
402
+ '__fxdriver_evaluate', '__fxdriver_unwrapped', '__webdriver_script_fn',
403
+ 'phantomjs', '_Selenium_IDE_Recorder', 'callSelenium', '_selenium',
404
+ '__phantomas', '__selenium_evaluate', '__driver_unwrapped',
405
+ 'webdriver-evaluate', '__webdriverFunc', 'driver-evaluate', '__driver-evaluate', '__selenium-evaluate',
402
406
  'spawn', 'emit', 'Buffer', 'domAutomation', 'domAutomationController'
403
407
  ];
404
408
 
@@ -449,15 +453,38 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
449
453
  let plugins = [];
450
454
  if (userAgent.includes('Chrome')) {
451
455
  plugins = [
452
- { name: 'Chrome PDF Plugin', description: 'Portable Document Format', filename: 'internal-pdf-viewer' },
453
- { name: 'Chrome PDF Viewer', description: 'PDF Viewer', filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai' }
456
+ {
457
+ name: 'Chrome PDF Plugin',
458
+ description: 'Portable Document Format',
459
+ filename: 'internal-pdf-viewer',
460
+ length: 1,
461
+ version: ''
462
+ },
463
+ {
464
+ name: 'Chrome PDF Viewer',
465
+ description: '',
466
+ filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai',
467
+ length: 1,
468
+ version: ''
469
+ }
454
470
  ];
455
471
  } else if (userAgent.includes('Firefox')) {
456
472
  plugins = [
457
- { name: 'PDF.js', description: 'Portable Document Format', filename: 'internal-pdf-js' }
473
+ {
474
+ name: 'PDF.js',
475
+ description: 'Portable Document Format',
476
+ filename: 'internal-pdf-js',
477
+ length: 2,
478
+ version: '5.4.70'
479
+ }
458
480
  ];
481
+ } else if (userAgent.includes('Safari')) {
482
+ // Safari typically has no plugins in modern versions
483
+ plugins = [];
459
484
  }
460
- safeDefinePropertyLocal(navigator, 'plugins', { get: () => plugins });
485
+ // Create array-like object with length property
486
+ const pluginsArray = Object.assign(plugins, { length: plugins.length });
487
+ safeDefinePropertyLocal(navigator, 'plugins', { get: () => pluginsArray });
461
488
  }, 'plugins spoofing');
462
489
 
463
490
  // Spoof languages
@@ -482,6 +509,69 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
482
509
  safeDefinePropertyLocal(navigator, 'product', { get: () => product });
483
510
  }, 'vendor/product spoofing');
484
511
 
512
+ // Enhanced OS fingerprinting protection based on actual user agent content
513
+ safeExecute(() => {
514
+ let osType = 'windows';
515
+ let browserType = 'chrome';
516
+
517
+ // Detect OS from user agent string patterns
518
+ if (userAgent.includes('Macintosh') || userAgent.includes('Mac OS X')) {
519
+ osType = 'mac';
520
+ } else if (userAgent.includes('X11; Linux') || userAgent.includes('Ubuntu')) {
521
+ osType = 'linux';
522
+ } else if (userAgent.includes('Windows NT')) {
523
+ osType = 'windows';
524
+ }
525
+
526
+ // Detect browser type
527
+ if (userAgent.includes('Firefox/')) {
528
+ browserType = 'firefox';
529
+ } else if (userAgent.includes('Safari/') && !userAgent.includes('Chrome/')) {
530
+ browserType = 'safari';
531
+ }
532
+
533
+ // Apply OS-specific navigator properties
534
+ if (osType === 'windows') {
535
+ if (browserType === 'firefox') {
536
+ safeDefinePropertyLocal(navigator, 'oscpu', { get: () => 'Windows NT 10.0; Win64; x64' });
537
+ safeDefinePropertyLocal(navigator, 'buildID', { get: () => '20100101' });
538
+ }
539
+ if (window.screen) {
540
+ safeDefinePropertyLocal(window.screen, 'fontSmoothingEnabled', { get: () => true });
541
+ }
542
+ } else if (osType === 'mac') {
543
+ if (browserType === 'firefox') {
544
+ safeDefinePropertyLocal(navigator, 'oscpu', { get: () => 'Intel Mac OS X 10.15' });
545
+ safeDefinePropertyLocal(navigator, 'buildID', { get: () => '20100101' });
546
+ }
547
+ } else if (osType === 'linux') {
548
+ if (browserType === 'firefox') {
549
+ safeDefinePropertyLocal(navigator, 'oscpu', { get: () => 'Linux x86_64' });
550
+ safeDefinePropertyLocal(navigator, 'buildID', { get: () => '20100101' });
551
+ }
552
+ }
553
+ }, 'enhanced OS fingerprinting protection');
554
+
555
+ // Screen resolution fingerprinting protection
556
+ safeExecute(() => {
557
+ // Common realistic resolutions to avoid fingerprinting
558
+ const commonResolutions = [
559
+ { width: 1920, height: 1080 },
560
+ { width: 2560, height: 1440 },
561
+ { width: 3840, height: 2160 },
562
+ { width: 1280, height: 720 },
563
+ { width: 1366, height: 768 },
564
+ { width: 1440, height: 900 },
565
+ { width: 1536, height: 864 }
566
+ ];
567
+ const resolution = commonResolutions[Math.floor(Math.random() * commonResolutions.length)];
568
+
569
+ safeDefinePropertyLocal(window.screen, 'width', { get: () => resolution.width });
570
+ safeDefinePropertyLocal(window.screen, 'height', { get: () => resolution.height });
571
+ safeDefinePropertyLocal(window.screen, 'availWidth', { get: () => resolution.width });
572
+ safeDefinePropertyLocal(window.screen, 'availHeight', { get: () => resolution.height - 40 });
573
+ }, 'screen resolution protection');
574
+
485
575
  // Spoof MIME types
486
576
  safeExecute(() => {
487
577
  let mimeTypes = [];
@@ -567,6 +657,134 @@ async function applyUserAgentSpoofing(page, siteConfig, forceDebug, currentUrl)
567
657
  }
568
658
  }, 'WebGL spoofing');
569
659
 
660
+ // Permissions API spoofing
661
+ safeExecute(() => {
662
+ if (navigator.permissions?.query) {
663
+ const originalQuery = navigator.permissions.query;
664
+ navigator.permissions.query = function(descriptor) {
665
+ return Promise.resolve({ state: Math.random() > 0.5 ? 'granted' : 'prompt' });
666
+ };
667
+ }
668
+ }, 'permissions API spoofing');
669
+
670
+ // Media Device Spoofing
671
+ safeExecute(() => {
672
+ if (navigator.mediaDevices?.enumerateDevices) {
673
+ navigator.mediaDevices.enumerateDevices = function() {
674
+ return Promise.resolve([
675
+ { deviceId: 'default', kind: 'audioinput', label: 'Default - Microphone (Realtek Audio)', groupId: 'group1' },
676
+ { deviceId: 'default', kind: 'audiooutput', label: 'Default - Speakers (Realtek Audio)', groupId: 'group1' },
677
+ { deviceId: 'default', kind: 'videoinput', label: 'HD WebCam (USB Camera)', groupId: 'group2' }
678
+ ]);
679
+ };
680
+ }
681
+ }, 'media device spoofing');
682
+
683
+ // Fetch Request Headers Normalization
684
+ safeExecute(() => {
685
+ const originalFetch = window.fetch;
686
+ window.fetch = function(url, options = {}) {
687
+ const headers = { ...(options.headers || {}) };
688
+
689
+ // Add common browser headers if missing
690
+ if (!headers['Accept']) {
691
+ headers['Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
692
+ }
693
+ if (!headers['Accept-Language']) {
694
+ headers['Accept-Language'] = 'en-US,en;q=0.5';
695
+ }
696
+ if (!headers['Accept-Encoding']) {
697
+ headers['Accept-Encoding'] = 'gzip, deflate, br';
698
+ }
699
+
700
+ return originalFetch.call(this, url, { ...options, headers });
701
+ };
702
+ }, 'fetch headers normalization');
703
+
704
+ // Image Loading Pattern Obfuscation
705
+ safeExecute(() => {
706
+ const originalImageSrc = Object.getOwnPropertyDescriptor(HTMLImageElement.prototype, 'src');
707
+ if (originalImageSrc) {
708
+ Object.defineProperty(HTMLImageElement.prototype, 'src', {
709
+ set: function(value) {
710
+ // Add random delay to image loading (0-50ms)
711
+ setTimeout(() => {
712
+ originalImageSrc.set.call(this, value);
713
+ }, Math.random() * 50);
714
+ },
715
+ get: originalImageSrc.get,
716
+ configurable: true
717
+ });
718
+ }
719
+ }, 'image loading obfuscation');
720
+
721
+ // CSS Media Query Spoofing
722
+ safeExecute(() => {
723
+ const originalMatchMedia = window.matchMedia;
724
+ window.matchMedia = function(query) {
725
+ const result = originalMatchMedia.call(this, query);
726
+ // Add slight randomization to avoid fingerprinting for device queries
727
+ if (query.includes('device-width') || query.includes('device-height') ||
728
+ query.includes('aspect-ratio') || query.includes('color-gamut')) {
729
+ Object.defineProperty(result, 'matches', {
730
+ get: () => Math.random() > 0.1 ? originalMatchMedia.call(window, query).matches : !originalMatchMedia.call(window, query).matches,
731
+ configurable: true
732
+ });
733
+ }
734
+ return result;
735
+ };
736
+ }, 'CSS media query spoofing');
737
+
738
+ // Enhanced WebRTC Spoofing
739
+ safeExecute(() => {
740
+ if (window.RTCPeerConnection) {
741
+ const OriginalRTC = window.RTCPeerConnection;
742
+ window.RTCPeerConnection = function(...args) {
743
+ const pc = new OriginalRTC(...args);
744
+ const originalCreateOffer = pc.createOffer;
745
+ pc.createOffer = function() {
746
+ return Promise.reject(new Error('WebRTC disabled'));
747
+ };
748
+ return pc;
749
+ };
750
+ Object.setPrototypeOf(window.RTCPeerConnection, OriginalRTC);
751
+ }
752
+ }, 'WebRTC spoofing');
753
+
754
+ // Font fingerprinting protection
755
+ safeExecute(() => {
756
+ // Standardize available fonts to common system fonts
757
+ const standardFonts = [
758
+ 'Arial', 'Helvetica', 'Times New Roman', 'Times', 'Courier New', 'Courier',
759
+ 'Verdana', 'Georgia', 'Palatino', 'Garamond', 'Bookman', 'Comic Sans MS',
760
+ 'Trebuchet MS', 'Arial Black', 'Impact', 'Tahoma', 'Lucida Console'
761
+ ];
762
+
763
+ // Override font detection methods
764
+ const originalOffsetWidth = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetWidth');
765
+ const originalOffsetHeight = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetHeight');
766
+
767
+ if (originalOffsetWidth && originalOffsetHeight) {
768
+ Object.defineProperty(HTMLElement.prototype, 'offsetWidth', {
769
+ get: function() {
770
+ if (this.style && this.style.fontFamily) {
771
+ return Math.floor(originalOffsetWidth.get.call(this) + (Math.random() - 0.5) * 2);
772
+ }
773
+ return originalOffsetWidth.get.call(this);
774
+ },
775
+ configurable: true
776
+ });
777
+ }
778
+ }, 'font fingerprinting protection');
779
+
780
+ // Performance timing obfuscation
781
+ safeExecute(() => {
782
+ const originalNow = performance.now;
783
+ performance.now = function() {
784
+ return originalNow.call(this) + (Math.random() - 0.5) * 2; // +/- 1ms variation
785
+ };
786
+ }, 'performance timing obfuscation');
787
+
570
788
  // Canvas fingerprinting protection
571
789
  safeExecute(() => {
572
790
  const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
@@ -811,6 +1029,17 @@ async function applyFingerprintProtection(page, siteConfig, forceDebug, currentU
811
1029
  // Memory spoofing
812
1030
  safeDefinePropertyLocal(navigator, 'deviceMemory', { get: () => spoof.deviceMemory });
813
1031
  safeDefinePropertyLocal(navigator, 'hardwareConcurrency', { get: () => spoof.hardwareConcurrency });
1032
+
1033
+ // Connection type spoofing
1034
+ safeDefinePropertyLocal(navigator, 'connection', {
1035
+ get: () => ({
1036
+ effectiveType: ['slow-2g', '2g', '3g', '4g'][Math.floor(Math.random() * 4)],
1037
+ type: Math.random() > 0.5 ? 'cellular' : 'wifi',
1038
+ saveData: Math.random() > 0.8,
1039
+ downlink: 1.5 + Math.random() * 8,
1040
+ rtt: 50 + Math.random() * 200
1041
+ })
1042
+ });
814
1043
 
815
1044
  // Screen properties spoofing
816
1045
  ['width', 'height', 'availWidth', 'availHeight', 'colorDepth', 'pixelDepth'].forEach(prop => {
package/nwss.js CHANGED
@@ -1,4 +1,4 @@
1
- // === Network scanner script (nwss.js) v2.0.12 ===
1
+ // === Network scanner script (nwss.js) v2.0.14 ===
2
2
 
3
3
  // puppeteer for browser automation, fs for file system operations, psl for domain parsing.
4
4
  // const pLimit = require('p-limit'); // Will be dynamically imported
@@ -130,7 +130,7 @@ const { navigateWithRedirectHandling, handleRedirectTimeout } = require('./lib/r
130
130
  const { monitorBrowserHealth, isBrowserHealthy, isQuicklyResponsive, performGroupWindowCleanup, performRealtimeWindowCleanup, trackPageForRealtime, updatePageUsage, cleanupPageBeforeReload } = require('./lib/browserhealth');
131
131
 
132
132
  // --- Script Configuration & Constants ---
133
- const VERSION = '2.0.12'; // Script version
133
+ const VERSION = '2.0.14'; // Script version
134
134
 
135
135
  // get startTime
136
136
  const startTime = Date.now();
@@ -2025,9 +2025,9 @@ function setupFrameHandling(page, forceDebug) {
2025
2025
  chrome: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
2026
2026
  chrome_mac: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
2027
2027
  chrome_linux: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
2028
- firefox: "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko/20100101 Firefox/142.0",
2029
- firefox_mac: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:142.0) Gecko/20100101 Firefox/142.0",
2030
- firefox_linux: "Mozilla/5.0 (X11; Linux x86_64; rv:142.0) Gecko/20100101 Firefox/142.0",
2028
+ firefox: "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko/20100101 Firefox/143.0",
2029
+ firefox_mac: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:142.0) Gecko/20100101 Firefox/143.0",
2030
+ firefox_linux: "Mozilla/5.0 (X11; Linux x86_64; rv:142.0) Gecko/20100101 Firefox/143.0",
2031
2031
  safari: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15"
2032
2032
  };
2033
2033
  curlUserAgent = userAgents[siteConfig.userAgent.toLowerCase()] || '';
@@ -3278,11 +3278,20 @@ function setupFrameHandling(page, forceDebug) {
3278
3278
 
3279
3279
  if (forceDebug) console.log(formatLogMessage('debug', `Standard reload #${i} completed for ${currentUrl}`));
3280
3280
  } catch (standardReloadErr) {
3281
- // Only warn for non-timeout errors
3282
- if (!standardReloadErr.message.includes('timeout')) {
3281
+ // Categorize errors into expected vs unexpected
3282
+ const isExpectedError = standardReloadErr.message.includes('timeout') ||
3283
+ standardReloadErr.message.includes('detached Frame') ||
3284
+ standardReloadErr.message.includes('Attempted to use detached') ||
3285
+ standardReloadErr.message.includes('Navigating frame was detached') ||
3286
+ standardReloadErr.message.includes('document invalid') ||
3287
+ standardReloadErr.message.includes('Page document invalid');
3288
+
3289
+ if (!isExpectedError) {
3290
+ // Only warn for truly unexpected errors
3283
3291
  console.warn(messageColors.warn(`[standard reload #${i} failed] ${currentUrl}: ${standardReloadErr.message}`));
3284
3292
  } else if (forceDebug) {
3285
- console.log(formatLogMessage('debug', `Reload #${i} timed out for ${currentUrl}, continuing anyway`));
3293
+ // Expected errors only shown in debug mode
3294
+ console.log(formatLogMessage('debug', `[reload #${i}] Expected error for ${currentUrl}: ${standardReloadErr.message}`));
3286
3295
  }
3287
3296
 
3288
3297
  // Check if this is a persistent failure that should skip remaining reloads
@@ -3993,4 +4002,4 @@ function setupFrameHandling(page, forceDebug) {
3993
4002
  if (forceDebug) console.log(formatLogMessage('debug', `About to exit process...`));
3994
4003
  process.exit(0);
3995
4004
 
3996
- })();
4005
+ })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fanboynz/network-scanner",
3
- "version": "2.0.12",
3
+ "version": "2.0.14",
4
4
  "description": "A Puppeteer-based network scanner for analyzing web traffic, generating adblock filter rules, and identifying third-party requests. Features include fingerprint spoofing, Cloudflare bypass, content analysis with curl/grep, and multiple output formats.",
5
5
  "main": "nwss.js",
6
6
  "scripts": {