@niksbanna/bot-detector 1.0.0 → 1.0.3
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/README.md +56 -2
- package/dist/bot-detector.cjs.js +115 -74
- package/dist/bot-detector.cjs.js.map +2 -2
- package/dist/bot-detector.esm.js +115 -74
- package/dist/bot-detector.esm.js.map +2 -2
- package/dist/bot-detector.iife.js +115 -74
- package/dist/bot-detector.iife.js.map +2 -2
- package/dist/bot-detector.iife.min.js +3 -1
- package/package.json +5 -4
- package/src/core/BotDetector.js +29 -18
- package/src/core/ScoringEngine.js +3 -2
- package/src/index.js +18 -10
- package/src/signals/automation/PhantomJSSignal.js +2 -4
- package/src/signals/automation/PlaywrightSignal.js +0 -6
- package/src/signals/automation/PuppeteerSignal.js +20 -14
- package/src/signals/automation/SeleniumSignal.js +2 -5
- package/src/signals/behavior/KeyboardPatternSignal.js +1 -1
- package/src/signals/behavior/MouseMovementSignal.js +1 -1
- package/src/signals/behavior/ScrollBehaviorSignal.js +1 -1
- package/src/signals/environment/HeadlessSignal.js +4 -4
- package/src/signals/environment/NavigatorAnomalySignal.js +3 -2
- package/src/signals/timing/DOMContentTimingSignal.js +2 -1
- package/src/signals/timing/PageLoadSignal.js +38 -20
|
@@ -35,30 +35,40 @@ class PageLoadSignal extends Signal {
|
|
|
35
35
|
|
|
36
36
|
const timing = performance.timing;
|
|
37
37
|
|
|
38
|
-
// Calculate key timings
|
|
38
|
+
// Calculate key timings.
|
|
39
|
+
// A 0 entry means the event hasn't fired; subtracting from a large epoch
|
|
40
|
+
// timestamp produces a huge negative number that was incorrectly flagged
|
|
41
|
+
// as 'negative-timing' (timestamp manipulation).
|
|
39
42
|
const navigationStart = timing.navigationStart;
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
const
|
|
43
|
+
const safeTimingDiff = (end, start) => {
|
|
44
|
+
if (end === 0 || start === 0) return null;
|
|
45
|
+
return end - start;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const domContentLoaded = safeTimingDiff(timing.domContentLoadedEventEnd, navigationStart);
|
|
49
|
+
const domComplete = safeTimingDiff(timing.domComplete, navigationStart);
|
|
50
|
+
const loadComplete = safeTimingDiff(timing.loadEventEnd, navigationStart);
|
|
51
|
+
const dnsLookup = safeTimingDiff(timing.domainLookupEnd, timing.domainLookupStart);
|
|
52
|
+
const tcpConnection = safeTimingDiff(timing.connectEnd, timing.connectStart);
|
|
53
|
+
const serverResponse = safeTimingDiff(timing.responseEnd, timing.requestStart);
|
|
54
|
+
const domProcessing = safeTimingDiff(timing.domComplete, timing.domLoading);
|
|
47
55
|
|
|
48
56
|
// Check for impossibly fast load times
|
|
49
|
-
if (domContentLoaded > 0 && domContentLoaded < 10) {
|
|
57
|
+
if (domContentLoaded !== null && domContentLoaded > 0 && domContentLoaded < 10) {
|
|
50
58
|
anomalies.push('instant-dom-content-loaded');
|
|
51
59
|
confidence = Math.max(confidence, 0.7);
|
|
52
60
|
}
|
|
53
61
|
|
|
54
62
|
// Check for zero DNS lookup (could indicate local file or caching, but suspicious in combination)
|
|
55
|
-
if (dnsLookup === 0 && tcpConnection === 0 && serverResponse < 5) {
|
|
63
|
+
if (dnsLookup === 0 && tcpConnection === 0 && serverResponse !== null && serverResponse < 5) {
|
|
56
64
|
anomalies.push('zero-network-timing');
|
|
57
65
|
confidence = Math.max(confidence, 0.4);
|
|
58
66
|
}
|
|
59
67
|
|
|
60
|
-
// Check for negative timings (timestamp manipulation)
|
|
61
|
-
if (domContentLoaded
|
|
68
|
+
// Check for negative timings (timestamp manipulation).
|
|
69
|
+
if ((domContentLoaded !== null && domContentLoaded < 0) ||
|
|
70
|
+
(domComplete !== null && domComplete < 0) ||
|
|
71
|
+
(loadComplete !== null && loadComplete < 0)) {
|
|
62
72
|
anomalies.push('negative-timing');
|
|
63
73
|
confidence = Math.max(confidence, 0.8);
|
|
64
74
|
}
|
|
@@ -72,7 +82,7 @@ class PageLoadSignal extends Signal {
|
|
|
72
82
|
}
|
|
73
83
|
|
|
74
84
|
// Check for very long processing times (could indicate headless waiting)
|
|
75
|
-
if (domProcessing > 30000) { // 30 seconds
|
|
85
|
+
if (domProcessing !== null && domProcessing > 30000) { // 30 seconds
|
|
76
86
|
anomalies.push('excessive-dom-processing');
|
|
77
87
|
confidence = Math.max(confidence, 0.3);
|
|
78
88
|
}
|
|
@@ -80,17 +90,25 @@ class PageLoadSignal extends Signal {
|
|
|
80
90
|
// Check for script injection timing pattern
|
|
81
91
|
// Bots often inject scripts immediately after load
|
|
82
92
|
const scriptsLoadedTime = timing.domContentLoadedEventStart - timing.responseEnd;
|
|
83
|
-
if (
|
|
93
|
+
if (timing.responseEnd > 0 && timing.domContentLoadedEventStart > 0 &&
|
|
94
|
+
scriptsLoadedTime > 0 && scriptsLoadedTime < 5) {
|
|
84
95
|
anomalies.push('instant-script-execution');
|
|
85
96
|
confidence = Math.max(confidence, 0.4);
|
|
86
97
|
}
|
|
87
98
|
|
|
88
|
-
// Check for performance.now() manipulation
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
99
|
+
// Check for performance.now() manipulation.
|
|
100
|
+
// performance.now() to 1-2ms for Spectre protection. Two consecutive calls
|
|
101
|
+
// can legitimately return the same value, so comparing only two is unreliable.
|
|
102
|
+
// Instead, use a busy-wait loop to advance time, then check if the clock moved.
|
|
103
|
+
const perfBefore = performance.now();
|
|
104
|
+
// Spin for ~1ms to force the clock to advance past quantization granularity
|
|
105
|
+
const spinEnd = perfBefore + 2;
|
|
106
|
+
// eslint-disable-next-line no-empty
|
|
107
|
+
while (performance.now() < spinEnd) {}
|
|
108
|
+
const perfAfter = performance.now();
|
|
109
|
+
|
|
110
|
+
if (perfAfter === perfBefore) {
|
|
111
|
+
// Clock truly didn't advance over 2ms — something is wrong
|
|
94
112
|
anomalies.push('frozen-performance-now');
|
|
95
113
|
confidence = Math.max(confidence, 0.6);
|
|
96
114
|
}
|