@niksbanna/bot-detector 1.0.0

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.
Files changed (38) hide show
  1. package/README.md +245 -0
  2. package/dist/bot-detector.cjs.js +2629 -0
  3. package/dist/bot-detector.cjs.js.map +7 -0
  4. package/dist/bot-detector.esm.js +2609 -0
  5. package/dist/bot-detector.esm.js.map +7 -0
  6. package/dist/bot-detector.iife.js +2631 -0
  7. package/dist/bot-detector.iife.js.map +7 -0
  8. package/dist/bot-detector.iife.min.js +1 -0
  9. package/package.json +57 -0
  10. package/src/core/BotDetector.js +284 -0
  11. package/src/core/ScoringEngine.js +134 -0
  12. package/src/core/Signal.js +181 -0
  13. package/src/core/VerdictEngine.js +132 -0
  14. package/src/index.js +273 -0
  15. package/src/signals/automation/PhantomJSSignal.js +137 -0
  16. package/src/signals/automation/PlaywrightSignal.js +129 -0
  17. package/src/signals/automation/PuppeteerSignal.js +117 -0
  18. package/src/signals/automation/SeleniumSignal.js +151 -0
  19. package/src/signals/automation/index.js +8 -0
  20. package/src/signals/behavior/InteractionTimingSignal.js +170 -0
  21. package/src/signals/behavior/KeyboardPatternSignal.js +235 -0
  22. package/src/signals/behavior/MouseMovementSignal.js +215 -0
  23. package/src/signals/behavior/ScrollBehaviorSignal.js +236 -0
  24. package/src/signals/behavior/index.js +8 -0
  25. package/src/signals/environment/HeadlessSignal.js +97 -0
  26. package/src/signals/environment/NavigatorAnomalySignal.js +117 -0
  27. package/src/signals/environment/PermissionsSignal.js +76 -0
  28. package/src/signals/environment/WebDriverSignal.js +58 -0
  29. package/src/signals/environment/index.js +8 -0
  30. package/src/signals/fingerprint/AudioContextSignal.js +158 -0
  31. package/src/signals/fingerprint/CanvasSignal.js +133 -0
  32. package/src/signals/fingerprint/PluginsSignal.js +106 -0
  33. package/src/signals/fingerprint/ScreenSignal.js +157 -0
  34. package/src/signals/fingerprint/WebGLSignal.js +146 -0
  35. package/src/signals/fingerprint/index.js +9 -0
  36. package/src/signals/timing/DOMContentTimingSignal.js +159 -0
  37. package/src/signals/timing/PageLoadSignal.js +165 -0
  38. package/src/signals/timing/index.js +6 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.js", "../src/core/Signal.js", "../src/core/ScoringEngine.js", "../src/core/VerdictEngine.js", "../src/core/BotDetector.js", "../src/signals/environment/WebDriverSignal.js", "../src/signals/environment/HeadlessSignal.js", "../src/signals/environment/NavigatorAnomalySignal.js", "../src/signals/environment/PermissionsSignal.js", "../src/signals/behavior/MouseMovementSignal.js", "../src/signals/behavior/KeyboardPatternSignal.js", "../src/signals/behavior/InteractionTimingSignal.js", "../src/signals/behavior/ScrollBehaviorSignal.js", "../src/signals/fingerprint/PluginsSignal.js", "../src/signals/fingerprint/WebGLSignal.js", "../src/signals/fingerprint/CanvasSignal.js", "../src/signals/fingerprint/AudioContextSignal.js", "../src/signals/fingerprint/ScreenSignal.js", "../src/signals/timing/PageLoadSignal.js", "../src/signals/timing/DOMContentTimingSignal.js", "../src/signals/automation/PuppeteerSignal.js", "../src/signals/automation/PlaywrightSignal.js", "../src/signals/automation/SeleniumSignal.js", "../src/signals/automation/PhantomJSSignal.js"],
4
+ "sourcesContent": ["/**\n * @fileoverview Main entry point for the bot detection library.\n * @module @niksbanna/bot-detector\n */\n\n// Core classes\nimport { BotDetector, Verdict } from './core/BotDetector.js';\nimport { Signal } from './core/Signal.js';\nimport { ScoringEngine } from './core/ScoringEngine.js';\nimport { VerdictEngine } from './core/VerdictEngine.js';\n\n// Environment signals\nimport {\n WebDriverSignal,\n HeadlessSignal,\n NavigatorAnomalySignal,\n PermissionsSignal,\n} from './signals/environment/index.js';\n\n// Behavioral signals\nimport {\n MouseMovementSignal,\n KeyboardPatternSignal,\n InteractionTimingSignal,\n ScrollBehaviorSignal,\n} from './signals/behavior/index.js';\n\n// Fingerprint signals\nimport {\n PluginsSignal,\n WebGLSignal,\n CanvasSignal,\n AudioContextSignal,\n ScreenSignal,\n} from './signals/fingerprint/index.js';\n\n// Timing signals\nimport {\n PageLoadSignal,\n DOMContentTimingSignal,\n} from './signals/timing/index.js';\n\n// Automation framework signals\nimport {\n PuppeteerSignal,\n PlaywrightSignal,\n SeleniumSignal,\n PhantomJSSignal,\n} from './signals/automation/index.js';\n\n/**\n * All built-in signal classes organized by category.\n */\nconst Signals = {\n // Environment signals\n WebDriverSignal,\n HeadlessSignal,\n NavigatorAnomalySignal,\n PermissionsSignal,\n \n // Behavioral signals\n MouseMovementSignal,\n KeyboardPatternSignal,\n InteractionTimingSignal,\n ScrollBehaviorSignal,\n \n // Fingerprint signals\n PluginsSignal,\n WebGLSignal,\n CanvasSignal,\n AudioContextSignal,\n ScreenSignal,\n \n // Timing signals\n PageLoadSignal,\n DOMContentTimingSignal,\n \n // Automation framework signals\n PuppeteerSignal,\n PlaywrightSignal,\n SeleniumSignal,\n PhantomJSSignal,\n};\n\n/**\n * Default signal instances that don't require user interaction.\n * These are suitable for immediate detection on page load.\n */\nconst defaultInstantSignals = [\n new WebDriverSignal(),\n new HeadlessSignal(),\n new NavigatorAnomalySignal(),\n new PermissionsSignal(),\n new PluginsSignal(),\n new WebGLSignal(),\n new CanvasSignal(),\n new AudioContextSignal(),\n new ScreenSignal(),\n new PageLoadSignal(),\n new DOMContentTimingSignal(),\n new PuppeteerSignal(),\n new PlaywrightSignal(),\n new SeleniumSignal(),\n new PhantomJSSignal(),\n];\n\n/**\n * Signal instances that require user interaction to be meaningful.\n * These track mouse, keyboard, and scroll behavior over time.\n */\nconst defaultInteractionSignals = [\n new MouseMovementSignal(),\n new KeyboardPatternSignal(),\n new InteractionTimingSignal(),\n new ScrollBehaviorSignal(),\n];\n\n/**\n * All default signal instances.\n */\nconst defaultSignals = [...defaultInstantSignals, ...defaultInteractionSignals];\n\n/**\n * Create a BotDetector with all default signals registered.\n * This is the recommended way to create a detector for most use cases.\n * \n * @param {Object} [options={}] - Configuration options\n * @param {Object.<string, number>} [options.weightOverrides={}] - Override signal weights\n * @param {number} [options.humanThreshold=20] - Score threshold for human verdict\n * @param {number} [options.suspiciousThreshold=50] - Score threshold for suspicious verdict\n * @param {Array<string>} [options.instantBotSignals=['webdriver', 'puppeteer', 'playwright', 'selenium', 'phantomjs']] - Signals that instantly flag as bot\n * @param {boolean} [options.includeInteractionSignals=true] - Include signals requiring interaction\n * @param {number} [options.detectionTimeout=5000] - Timeout for detection in ms\n * @returns {BotDetector}\n * \n * @example\n * // Basic usage\n * const detector = createDetector();\n * const result = await detector.detect();\n * \n * @example\n * // Custom thresholds\n * const detector = createDetector({\n * humanThreshold: 15,\n * suspiciousThreshold: 40,\n * });\n * \n * @example\n * // Skip interaction signals for instant detection\n * const detector = createDetector({\n * includeInteractionSignals: false,\n * });\n */\nfunction createDetector(options = {}) {\n const {\n includeInteractionSignals = true,\n instantBotSignals = ['webdriver', 'puppeteer', 'playwright', 'selenium', 'phantomjs'],\n ...detectorOptions\n } = options;\n\n const signals = includeInteractionSignals \n ? [...defaultInstantSignals, ...defaultInteractionSignals.map(s => {\n // Create fresh instances for interaction signals\n const SignalClass = s.constructor;\n return new SignalClass(s.options);\n })]\n : defaultInstantSignals.map(s => {\n const SignalClass = s.constructor;\n return new SignalClass(s.options);\n });\n\n return new BotDetector({\n signals,\n instantBotSignals,\n ...detectorOptions,\n });\n}\n\n/**\n * Quick detection function for simple use cases.\n * Creates a detector, runs detection, and returns result.\n * \n * @param {Object} [options={}] - Detection options\n * @param {boolean} [options.skipInteractionSignals=false] - Skip signals requiring interaction\n * @returns {Promise<DetectionResult>}\n * \n * @example\n * const result = await detect();\n * if (result.verdict === 'bot') {\n * console.log('Bot detected!', result.score);\n * }\n */\nasync function detect(options = {}) {\n const detector = createDetector({\n includeInteractionSignals: !options.skipInteractionSignals,\n });\n return detector.detect(options);\n}\n\n/**\n * Quick detection that only runs instant signals (no interaction required).\n * Suitable for immediate detection on page load.\n * \n * @returns {Promise<DetectionResult>}\n * \n * @example\n * document.addEventListener('DOMContentLoaded', async () => {\n * const result = await detectInstant();\n * console.log('Verdict:', result.verdict);\n * });\n */\nasync function detectInstant() {\n return detect({ skipInteractionSignals: true });\n}\n\n// Export everything\nexport {\n // Main class\n BotDetector,\n \n // Factory functions\n createDetector,\n detect,\n detectInstant,\n \n // Base classes\n Signal,\n ScoringEngine,\n VerdictEngine,\n \n // Enums\n Verdict,\n \n // Signal classes (for custom registration)\n Signals,\n \n // Individual signals\n WebDriverSignal,\n HeadlessSignal,\n NavigatorAnomalySignal,\n PermissionsSignal,\n MouseMovementSignal,\n KeyboardPatternSignal,\n InteractionTimingSignal,\n ScrollBehaviorSignal,\n PluginsSignal,\n WebGLSignal,\n CanvasSignal,\n AudioContextSignal,\n ScreenSignal,\n PageLoadSignal,\n DOMContentTimingSignal,\n PuppeteerSignal,\n PlaywrightSignal,\n SeleniumSignal,\n PhantomJSSignal,\n \n // Default signal instances\n defaultSignals,\n defaultInstantSignals,\n defaultInteractionSignals,\n};\n\n// Default export for convenience\nexport default {\n BotDetector,\n createDetector,\n detect,\n detectInstant,\n Signal,\n Signals,\n Verdict,\n};\n", "/**\n * @fileoverview Base Signal class for bot detection signals.\n * All signal detectors must extend this class.\n */\n\n/**\n * Base class for all signal detectors.\n * Signals detect specific indicators of automated browser behavior.\n * \n * @abstract\n * @example\n * class CustomSignal extends Signal {\n * static id = 'custom-signal';\n * static category = 'custom';\n * static weight = 0.5;\n * static description = 'Detects custom bot behavior';\n * \n * async detect() {\n * const isSuspicious = // ... detection logic\n * return {\n * triggered: isSuspicious,\n * value: someValue,\n * confidence: 0.8\n * };\n * }\n * }\n */\nclass Signal {\n /**\n * Unique identifier for this signal.\n * @type {string}\n */\n static id = 'base-signal';\n\n /**\n * Category this signal belongs to.\n * Categories: 'environment', 'behavior', 'fingerprint', 'timing', 'automation'\n * @type {string}\n */\n static category = 'uncategorized';\n\n /**\n * Weight of this signal in the scoring calculation.\n * Range: 0.1 (low importance) to 1.0 (high importance)\n * @type {number}\n */\n static weight = 0.5;\n\n /**\n * Human-readable description of what this signal detects.\n * @type {string}\n */\n static description = 'Base signal class';\n\n /**\n * Whether this signal requires user interaction before it can detect.\n * @type {boolean}\n */\n static requiresInteraction = false;\n\n /**\n * Creates a new Signal instance.\n * @param {Object} [options={}] - Configuration options for this signal.\n */\n constructor(options = {}) {\n this.options = options;\n this._lastResult = null;\n }\n\n /**\n * Get the signal's unique identifier.\n * @returns {string}\n */\n get id() {\n return this.constructor.id;\n }\n\n /**\n * Get the signal's category.\n * @returns {string}\n */\n get category() {\n return this.constructor.category;\n }\n\n /**\n * Get the signal's weight.\n * @returns {number}\n */\n get weight() {\n return this.options.weight ?? this.constructor.weight;\n }\n\n /**\n * Get the signal's description.\n * @returns {string}\n */\n get description() {\n return this.constructor.description;\n }\n\n /**\n * Check if this signal requires interaction.\n * @returns {boolean}\n */\n get requiresInteraction() {\n return this.constructor.requiresInteraction;\n }\n\n /**\n * Get the last detection result.\n * @returns {SignalResult|null}\n */\n get lastResult() {\n return this._lastResult;\n }\n\n /**\n * Perform the detection check.\n * Must be overridden by subclasses.\n * \n * @abstract\n * @returns {Promise<SignalResult>} Detection result\n * @throws {Error} If not implemented by subclass\n */\n async detect() {\n throw new Error(`Signal.detect() must be implemented by ${this.constructor.name}`);\n }\n\n /**\n * Run detection and cache the result.\n * @returns {Promise<SignalResult>}\n */\n async run() {\n try {\n this._lastResult = await this.detect();\n return this._lastResult;\n } catch (error) {\n // Fail-safe: if detection throws, treat as not triggered\n this._lastResult = {\n triggered: false,\n value: null,\n confidence: 0,\n error: error.message,\n };\n return this._lastResult;\n }\n }\n\n /**\n * Reset the signal state.\n */\n reset() {\n this._lastResult = null;\n }\n\n /**\n * Create a result object with defaults.\n * @param {boolean} triggered - Whether the signal was triggered\n * @param {*} [value=null] - Optional value associated with the detection\n * @param {number} [confidence=1] - Confidence level (0-1)\n * @returns {SignalResult}\n */\n createResult(triggered, value = null, confidence = 1) {\n return {\n triggered: Boolean(triggered),\n value,\n confidence: Math.max(0, Math.min(1, confidence)),\n };\n }\n}\n\n/**\n * @typedef {Object} SignalResult\n * @property {boolean} triggered - Whether the signal detected bot behavior\n * @property {*} value - Associated value or evidence\n * @property {number} confidence - Confidence level between 0 and 1\n * @property {string} [error] - Error message if detection failed\n */\n\nexport { Signal };\n", "/**\n * @fileoverview Scoring engine that calculates bot probability from signals.\n */\n\n/**\n * Calculates a weighted score from signal results.\n * Score represents the probability of the visitor being a bot.\n */\nclass ScoringEngine {\n /**\n * Creates a new ScoringEngine instance.\n * @param {Object} [options={}] - Configuration options\n * @param {Object.<string, number>} [options.weightOverrides={}] - Override weights by signal ID\n * @param {number} [options.maxScore=100] - Maximum possible score\n */\n constructor(options = {}) {\n this.weightOverrides = options.weightOverrides || {};\n this.maxScore = options.maxScore || 100;\n this._results = new Map();\n }\n\n /**\n * Get the effective weight for a signal.\n * @param {string} signalId - Signal identifier\n * @param {number} defaultWeight - Default weight from signal definition\n * @returns {number}\n */\n getWeight(signalId, defaultWeight) {\n return this.weightOverrides[signalId] ?? defaultWeight;\n }\n\n /**\n * Add a signal result to the scoring calculation.\n * @param {string} signalId - Signal identifier\n * @param {Object} result - Signal detection result\n * @param {boolean} result.triggered - Whether signal was triggered\n * @param {number} result.confidence - Confidence level (0-1)\n * @param {number} weight - Signal weight (0.1-1.0)\n */\n addResult(signalId, result, weight) {\n const effectiveWeight = this.getWeight(signalId, weight);\n this._results.set(signalId, {\n ...result,\n weight: effectiveWeight,\n contribution: result.triggered ? effectiveWeight * result.confidence : 0,\n });\n }\n\n /**\n * Calculate the final score from all added results.\n * Formula: (sum of contributions / sum of weights) * maxScore\n * \n * @returns {number} Score between 0 and maxScore\n */\n calculate() {\n if (this._results.size === 0) {\n return 0;\n }\n\n let totalWeight = 0;\n let totalContribution = 0;\n\n for (const [, data] of this._results) {\n totalWeight += data.weight;\n totalContribution += data.contribution;\n }\n\n if (totalWeight === 0) {\n return 0;\n }\n\n const score = (totalContribution / totalWeight) * this.maxScore;\n return Math.round(score * 100) / 100; // Round to 2 decimal places\n }\n\n /**\n * Get detailed breakdown of score contributions.\n * @returns {Array<Object>} Array of signal contributions\n */\n getBreakdown() {\n const breakdown = [];\n \n for (const [signalId, data] of this._results) {\n breakdown.push({\n signalId,\n triggered: data.triggered,\n confidence: data.confidence,\n weight: data.weight,\n contribution: data.contribution,\n percentOfScore: this.calculate() > 0 \n ? (data.contribution / this.calculate() * 100).toFixed(1)\n : '0.0',\n });\n }\n\n // Sort by contribution (highest first)\n return breakdown.sort((a, b) => b.contribution - a.contribution);\n }\n\n /**\n * Get all triggered signals.\n * @returns {Array<string>} Array of triggered signal IDs\n */\n getTriggeredSignals() {\n const triggered = [];\n for (const [signalId, data] of this._results) {\n if (data.triggered) {\n triggered.push(signalId);\n }\n }\n return triggered;\n }\n\n /**\n * Get the number of triggered signals.\n * @returns {number}\n */\n getTriggeredCount() {\n let count = 0;\n for (const [, data] of this._results) {\n if (data.triggered) count++;\n }\n return count;\n }\n\n /**\n * Reset all stored results.\n */\n reset() {\n this._results.clear();\n }\n}\n\nexport { ScoringEngine };\n", "/**\n * @fileoverview Verdict engine that determines bot/human classification.\n */\n\n/**\n * Possible verdicts from detection.\n * @enum {string}\n */\nconst Verdict = {\n HUMAN: 'human',\n SUSPICIOUS: 'suspicious',\n BOT: 'bot',\n};\n\n/**\n * Determines the final verdict based on score and triggered signals.\n */\nclass VerdictEngine {\n /**\n * Default threshold configuration.\n * @type {Object}\n */\n static DEFAULT_THRESHOLDS = {\n human: 20, // score < 20 = human\n suspicious: 50, // 20 <= score < 50 = suspicious\n // score >= 50 = bot\n };\n\n /**\n * Creates a new VerdictEngine instance.\n * @param {Object} [options={}] - Configuration options\n * @param {number} [options.humanThreshold=20] - Max score for human verdict\n * @param {number} [options.suspiciousThreshold=50] - Max score for suspicious verdict\n * @param {Array<string>} [options.instantBotSignals=[]] - Signal IDs that instantly flag as bot\n */\n constructor(options = {}) {\n this.humanThreshold = options.humanThreshold ?? VerdictEngine.DEFAULT_THRESHOLDS.human;\n this.suspiciousThreshold = options.suspiciousThreshold ?? VerdictEngine.DEFAULT_THRESHOLDS.suspicious;\n this.instantBotSignals = new Set(options.instantBotSignals || []);\n }\n\n /**\n * Get the verdict based on score and triggered signals.\n * @param {number} score - Calculated score (0-100)\n * @param {Array<string>} triggeredSignals - List of triggered signal IDs\n * @returns {VerdictResult}\n */\n getVerdict(score, triggeredSignals = []) {\n // Check for instant bot signals first\n for (const signalId of triggeredSignals) {\n if (this.instantBotSignals.has(signalId)) {\n return {\n verdict: Verdict.BOT,\n score,\n confidence: 'high',\n reason: `Instant bot signal triggered: ${signalId}`,\n triggeredCount: triggeredSignals.length,\n };\n }\n }\n\n // Score-based verdict\n let verdict;\n let confidence;\n let reason;\n\n if (score < this.humanThreshold) {\n verdict = Verdict.HUMAN;\n confidence = score < 10 ? 'high' : 'medium';\n reason = 'Low bot score';\n } else if (score < this.suspiciousThreshold) {\n verdict = Verdict.SUSPICIOUS;\n confidence = 'medium';\n reason = 'Moderate bot indicators detected';\n } else {\n verdict = Verdict.BOT;\n confidence = score >= 75 ? 'high' : 'medium';\n reason = 'High accumulation of bot indicators';\n }\n\n return {\n verdict,\n score,\n confidence,\n reason,\n triggeredCount: triggeredSignals.length,\n };\n }\n\n /**\n * Check if signal should instantly flag as bot.\n * @param {string} signalId - Signal identifier\n * @returns {boolean}\n */\n isInstantBotSignal(signalId) {\n return this.instantBotSignals.has(signalId);\n }\n\n /**\n * Add a signal to the instant bot list.\n * @param {string} signalId - Signal identifier\n */\n addInstantBotSignal(signalId) {\n this.instantBotSignals.add(signalId);\n }\n\n /**\n * Update thresholds.\n * @param {Object} thresholds - New threshold values\n * @param {number} [thresholds.human] - New human threshold\n * @param {number} [thresholds.suspicious] - New suspicious threshold\n */\n setThresholds(thresholds) {\n if (thresholds.human !== undefined) {\n this.humanThreshold = thresholds.human;\n }\n if (thresholds.suspicious !== undefined) {\n this.suspiciousThreshold = thresholds.suspicious;\n }\n }\n}\n\n/**\n * @typedef {Object} VerdictResult\n * @property {string} verdict - 'human', 'suspicious', or 'bot'\n * @property {number} score - The calculated score\n * @property {string} confidence - 'low', 'medium', or 'high'\n * @property {string} reason - Human-readable reason for verdict\n * @property {number} triggeredCount - Number of triggered signals\n */\n\nexport { VerdictEngine, Verdict };\n", "/**\n * @fileoverview Main BotDetector orchestrator class.\n */\n\nimport { Signal } from './Signal.js';\nimport { ScoringEngine } from './ScoringEngine.js';\nimport { VerdictEngine, Verdict } from './VerdictEngine.js';\n\n/**\n * Main bot detection orchestrator.\n * Manages signals, runs detection, and produces verdicts.\n * \n * @example\n * const detector = new BotDetector();\n * const result = await detector.detect();\n * console.log(result.verdict); // 'human', 'suspicious', or 'bot'\n */\nclass BotDetector {\n /**\n * Creates a new BotDetector instance.\n * @param {Object} [options={}] - Configuration options\n * @param {Array<Signal>} [options.signals=[]] - Initial signals to register\n * @param {Object.<string, number>} [options.weightOverrides={}] - Override signal weights\n * @param {number} [options.humanThreshold=20] - Score threshold for human verdict\n * @param {number} [options.suspiciousThreshold=50] - Score threshold for suspicious verdict\n * @param {Array<string>} [options.instantBotSignals=[]] - Signal IDs that instantly flag as bot\n * @param {boolean} [options.includeDefaults=true] - Include built-in signal detectors\n * @param {number} [options.detectionTimeout=5000] - Timeout for detection in ms\n */\n constructor(options = {}) {\n this.options = options;\n this._signals = new Map();\n this._scoringEngine = new ScoringEngine({\n weightOverrides: options.weightOverrides,\n });\n this._verdictEngine = new VerdictEngine({\n humanThreshold: options.humanThreshold,\n suspiciousThreshold: options.suspiciousThreshold,\n instantBotSignals: options.instantBotSignals,\n });\n this._lastDetection = null;\n this._detectionTimeout = options.detectionTimeout || 5000;\n this._isRunning = false;\n\n // Register initial signals\n if (options.signals) {\n for (const signal of options.signals) {\n this.registerSignal(signal);\n }\n }\n }\n\n /**\n * Register a signal detector.\n * @param {Signal} signal - Signal instance to register\n * @returns {BotDetector} this instance for chaining\n * @throws {Error} If signal with same ID already registered\n */\n registerSignal(signal) {\n if (!(signal instanceof Signal)) {\n throw new Error('Signal must be an instance of Signal class');\n }\n \n const id = signal.id;\n if (this._signals.has(id)) {\n throw new Error(`Signal with ID \"${id}\" is already registered`);\n }\n \n this._signals.set(id, signal);\n return this;\n }\n\n /**\n * Register multiple signals at once.\n * @param {Array<Signal>} signals - Array of signal instances\n * @returns {BotDetector} this instance for chaining\n */\n registerSignals(signals) {\n for (const signal of signals) {\n this.registerSignal(signal);\n }\n return this;\n }\n\n /**\n * Unregister a signal by ID.\n * @param {string} signalId - Signal ID to remove\n * @returns {boolean} True if signal was removed\n */\n unregisterSignal(signalId) {\n return this._signals.delete(signalId);\n }\n\n /**\n * Get a registered signal by ID.\n * @param {string} signalId - Signal ID\n * @returns {Signal|undefined}\n */\n getSignal(signalId) {\n return this._signals.get(signalId);\n }\n\n /**\n * Get all registered signals.\n * @returns {Array<Signal>}\n */\n getSignals() {\n return Array.from(this._signals.values());\n }\n\n /**\n * Get signals by category.\n * @param {string} category - Category name\n * @returns {Array<Signal>}\n */\n getSignalsByCategory(category) {\n return this.getSignals().filter(s => s.category === category);\n }\n\n /**\n * Run all signal detectors and calculate verdict.\n * @param {Object} [options={}] - Detection options\n * @param {boolean} [options.skipInteractionSignals=false] - Skip signals requiring interaction\n * @returns {Promise<DetectionResult>}\n */\n async detect(options = {}) {\n if (this._isRunning) {\n throw new Error('Detection is already running');\n }\n\n this._isRunning = true;\n this._scoringEngine.reset();\n\n const startTime = performance.now();\n const signalResults = new Map();\n \n try {\n // Filter signals based on options\n const signalsToRun = this.getSignals().filter(signal => {\n if (options.skipInteractionSignals && signal.requiresInteraction) {\n return false;\n }\n return true;\n });\n\n // Run all signals with timeout\n const detectionPromises = signalsToRun.map(async signal => {\n const result = await Promise.race([\n signal.run(),\n new Promise(resolve => \n setTimeout(() => resolve({ \n triggered: false, \n value: null, \n confidence: 0, \n error: 'timeout' \n }), this._detectionTimeout)\n ),\n ]);\n \n return { signal, result };\n });\n\n const results = await Promise.all(detectionPromises);\n\n // Process results\n for (const { signal, result } of results) {\n signalResults.set(signal.id, {\n ...result,\n category: signal.category,\n weight: signal.weight,\n description: signal.description,\n });\n\n this._scoringEngine.addResult(signal.id, result, signal.weight);\n }\n\n // Calculate score and verdict\n const score = this._scoringEngine.calculate();\n const triggeredSignals = this._scoringEngine.getTriggeredSignals();\n const verdict = this._verdictEngine.getVerdict(score, triggeredSignals);\n\n const detectionTime = performance.now() - startTime;\n\n this._lastDetection = {\n ...verdict,\n signals: Object.fromEntries(signalResults),\n breakdown: this._scoringEngine.getBreakdown(),\n timestamp: Date.now(),\n detectionTimeMs: Math.round(detectionTime),\n totalSignals: signalsToRun.length,\n triggeredSignals,\n };\n\n return this._lastDetection;\n } finally {\n this._isRunning = false;\n }\n }\n\n /**\n * Get the last detection result.\n * @returns {DetectionResult|null}\n */\n getLastDetection() {\n return this._lastDetection;\n }\n\n /**\n * Get the current score (from last detection).\n * @returns {number}\n */\n getScore() {\n return this._lastDetection?.score ?? 0;\n }\n\n /**\n * Get triggered signals from last detection.\n * @returns {Array<string>}\n */\n getTriggeredSignals() {\n return this._lastDetection?.triggeredSignals ?? [];\n }\n\n /**\n * Check if detection is currently running.\n * @returns {boolean}\n */\n isRunning() {\n return this._isRunning;\n }\n\n /**\n * Reset the detector state.\n */\n reset() {\n this._scoringEngine.reset();\n this._lastDetection = null;\n for (const signal of this._signals.values()) {\n signal.reset();\n }\n }\n\n /**\n * Update configuration options.\n * @param {Object} options - New options\n */\n configure(options) {\n if (options.humanThreshold !== undefined || options.suspiciousThreshold !== undefined) {\n this._verdictEngine.setThresholds({\n human: options.humanThreshold,\n suspicious: options.suspiciousThreshold,\n });\n }\n if (options.detectionTimeout !== undefined) {\n this._detectionTimeout = options.detectionTimeout;\n }\n }\n\n /**\n * Create a detector with default signals.\n * @param {Object} [options={}] - Configuration options\n * @returns {BotDetector}\n */\n static withDefaults(options = {}) {\n // This will be populated with default signals in the main export\n return new BotDetector(options);\n }\n}\n\n/**\n * @typedef {Object} DetectionResult\n * @property {string} verdict - 'human', 'suspicious', or 'bot'\n * @property {number} score - Calculated score (0-100)\n * @property {string} confidence - Confidence level\n * @property {string} reason - Reason for verdict\n * @property {Object} signals - Map of signal ID to results\n * @property {Array<Object>} breakdown - Score contribution breakdown\n * @property {number} timestamp - Detection timestamp\n * @property {number} detectionTimeMs - Time taken for detection\n * @property {number} totalSignals - Total signals evaluated\n * @property {Array<string>} triggeredSignals - IDs of triggered signals\n */\n\nexport { BotDetector, Verdict };\n", "/**\n * @fileoverview Detects navigator.webdriver property.\n * This is the most reliable indicator of WebDriver-controlled browsers.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Detects the presence of navigator.webdriver property.\n * This property is set to true by automation frameworks like Selenium, Puppeteer, and Playwright.\n */\nclass WebDriverSignal extends Signal {\n static id = 'webdriver';\n static category = 'environment';\n static weight = 1.0;\n static description = 'Detects navigator.webdriver automation flag';\n\n async detect() {\n // Direct check\n if (navigator.webdriver === true) {\n return this.createResult(true, { webdriver: true }, 1.0);\n }\n\n // Check if property exists but is hidden/modified\n const descriptor = Object.getOwnPropertyDescriptor(navigator, 'webdriver');\n if (descriptor) {\n // Property exists - check if it's been tampered with\n if (descriptor.get || !descriptor.configurable) {\n return this.createResult(true, { \n webdriver: 'modified',\n descriptor: {\n configurable: descriptor.configurable,\n enumerable: descriptor.enumerable,\n hasGetter: !!descriptor.get,\n }\n }, 0.8);\n }\n }\n\n // Check prototype chain for webdriver\n try {\n const proto = Object.getPrototypeOf(navigator);\n const protoDescriptor = Object.getOwnPropertyDescriptor(proto, 'webdriver');\n if (protoDescriptor && protoDescriptor.get) {\n const value = protoDescriptor.get.call(navigator);\n if (value === true) {\n return this.createResult(true, { webdriver: true, source: 'prototype' }, 1.0);\n }\n }\n } catch (e) {\n // Some environments may throw on prototype access\n }\n\n return this.createResult(false);\n }\n}\n\nexport { WebDriverSignal };\n", "/**\n * @fileoverview Detects headless browser indicators.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Detects indicators of headless browser execution.\n * Headless browsers often have missing or inconsistent features.\n */\nclass HeadlessSignal extends Signal {\n static id = 'headless';\n static category = 'environment';\n static weight = 0.8;\n static description = 'Detects headless browser indicators';\n\n async detect() {\n const indicators = [];\n let confidence = 0;\n\n // Check for HeadlessChrome in user agent\n const ua = navigator.userAgent || '';\n if (ua.includes('HeadlessChrome')) {\n indicators.push('headless-ua');\n confidence = Math.max(confidence, 1.0);\n }\n\n // Check for missing chrome.runtime in Chrome\n if (ua.includes('Chrome') && !ua.includes('Chromium')) {\n if (typeof window.chrome === 'undefined') {\n indicators.push('missing-chrome-object');\n confidence = Math.max(confidence, 0.6);\n } else if (!window.chrome.runtime) {\n indicators.push('missing-chrome-runtime');\n confidence = Math.max(confidence, 0.4);\n }\n }\n\n // Check for empty plugins (common in headless)\n if (navigator.plugins && navigator.plugins.length === 0) {\n indicators.push('no-plugins');\n confidence = Math.max(confidence, 0.5);\n }\n\n // Check for missing languages\n if (!navigator.languages || navigator.languages.length === 0) {\n indicators.push('no-languages');\n confidence = Math.max(confidence, 0.6);\n }\n\n // Check window dimensions anomalies\n if (window.outerWidth === 0 && window.outerHeight === 0) {\n indicators.push('zero-outer-dimensions');\n confidence = Math.max(confidence, 0.7);\n }\n\n // Check for missing connection info\n if (typeof navigator.connection === 'undefined' && ua.includes('Chrome')) {\n indicators.push('missing-connection-api');\n confidence = Math.max(confidence, 0.3);\n }\n\n // Check for Notification API permission inconsistency\n try {\n if (typeof Notification !== 'undefined' && Notification.permission === 'denied' &&\n window.outerWidth === 0) {\n indicators.push('notification-headless-pattern');\n confidence = Math.max(confidence, 0.5);\n }\n } catch (e) {\n // Ignore errors\n }\n\n // Phantom.js specific check\n if (window.callPhantom || window._phantom) {\n indicators.push('phantomjs');\n confidence = Math.max(confidence, 1.0);\n }\n\n // Nightmare.js check\n if (window.__nightmare) {\n indicators.push('nightmare');\n confidence = Math.max(confidence, 1.0);\n }\n\n const triggered = indicators.length > 0;\n \n // Increase confidence if multiple indicators are present\n if (indicators.length >= 3) {\n confidence = Math.min(1.0, confidence + 0.2);\n }\n\n return this.createResult(triggered, { indicators }, confidence);\n }\n}\n\nexport { HeadlessSignal };\n", "/**\n * @fileoverview Detects navigator property anomalies and inconsistencies.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Detects inconsistencies in navigator properties.\n * Bots often have mismatched or spoofed navigator values.\n */\nclass NavigatorAnomalySignal extends Signal {\n static id = 'navigator-anomaly';\n static category = 'environment';\n static weight = 0.7;\n static description = 'Detects navigator property inconsistencies';\n\n async detect() {\n const anomalies = [];\n let totalScore = 0;\n let checksPerformed = 0;\n\n const ua = navigator.userAgent || '';\n const platform = navigator.platform || '';\n\n // Platform vs UserAgent consistency check\n checksPerformed++;\n if (platform.includes('Win') && !ua.includes('Windows')) {\n anomalies.push('platform-ua-mismatch-windows');\n totalScore += 1;\n } else if (platform.includes('Mac') && !ua.includes('Mac')) {\n anomalies.push('platform-ua-mismatch-mac');\n totalScore += 1;\n } else if (platform.includes('Linux') && !ua.includes('Linux') && !ua.includes('Android')) {\n anomalies.push('platform-ua-mismatch-linux');\n totalScore += 1;\n }\n\n // Check for empty or suspicious platform\n checksPerformed++;\n if (!platform || platform === '' || platform === 'undefined') {\n anomalies.push('empty-platform');\n totalScore += 1;\n }\n\n // Language consistency\n checksPerformed++;\n if (navigator.language && navigator.languages) {\n if (!navigator.languages.includes(navigator.language)) {\n anomalies.push('language-mismatch');\n totalScore += 0.5;\n }\n }\n\n // Check vendor consistency with browser\n checksPerformed++;\n if (ua.includes('Chrome') && navigator.vendor !== 'Google Inc.') {\n anomalies.push('vendor-mismatch-chrome');\n totalScore += 0.5;\n } else if (ua.includes('Firefox') && navigator.vendor !== '') {\n anomalies.push('vendor-mismatch-firefox');\n totalScore += 0.5;\n } else if (ua.includes('Safari') && !ua.includes('Chrome') && \n navigator.vendor !== 'Apple Computer, Inc.') {\n anomalies.push('vendor-mismatch-safari');\n totalScore += 0.5;\n }\n\n // Check for hardwareConcurrency anomaly\n checksPerformed++;\n if (typeof navigator.hardwareConcurrency !== 'undefined') {\n if (navigator.hardwareConcurrency === 0 || navigator.hardwareConcurrency > 128) {\n anomalies.push('suspicious-hardware-concurrency');\n totalScore += 0.5;\n }\n }\n\n // Check deviceMemory if available\n checksPerformed++;\n if (typeof navigator.deviceMemory !== 'undefined') {\n if (navigator.deviceMemory === 0 || navigator.deviceMemory > 512) {\n anomalies.push('suspicious-device-memory');\n totalScore += 0.5;\n }\n }\n\n // Check maxTouchPoints consistency\n checksPerformed++;\n const isMobileUA = /Android|iPhone|iPad|iPod|Mobile/i.test(ua);\n const hasTouchPoints = navigator.maxTouchPoints > 0;\n \n // Desktop claiming touch or mobile with no touch\n if (!isMobileUA && navigator.maxTouchPoints > 5) {\n anomalies.push('desktop-high-touch-points');\n totalScore += 0.3;\n }\n\n // Check for overridden properties (common in spoofing)\n checksPerformed++;\n try {\n const desc = Object.getOwnPropertyDescriptor(Navigator.prototype, 'userAgent');\n if (desc && desc.get && desc.get.toString().includes('native code') === false) {\n anomalies.push('spoofed-user-agent');\n totalScore += 1;\n }\n } catch (e) {\n // Ignore errors\n }\n\n // Calculate confidence based on number and severity of anomalies\n const triggered = anomalies.length > 0;\n const confidence = Math.min(1, totalScore / Math.max(1, checksPerformed));\n\n return this.createResult(triggered, { anomalies }, confidence);\n }\n}\n\nexport { NavigatorAnomalySignal };\n", "/**\n * @fileoverview Detects permissions API anomalies.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Detects anomalies in the Permissions API.\n * Automation tools often have inconsistent permission states.\n */\nclass PermissionsSignal extends Signal {\n static id = 'permissions';\n static category = 'environment';\n static weight = 0.5;\n static description = 'Detects Permissions API anomalies';\n\n async detect() {\n const anomalies = [];\n \n // Check if Permissions API exists\n if (!navigator.permissions) {\n // Not an anomaly, just not supported\n return this.createResult(false, { supported: false }, 0);\n }\n\n try {\n // Check notification permission consistency\n const notificationStatus = await navigator.permissions.query({ name: 'notifications' });\n \n if (typeof Notification !== 'undefined') {\n const directPermission = Notification.permission;\n \n // Check for mismatch\n if ((directPermission === 'granted' && notificationStatus.state !== 'granted') ||\n (directPermission === 'denied' && notificationStatus.state !== 'denied') ||\n (directPermission === 'default' && notificationStatus.state !== 'prompt')) {\n anomalies.push('notification-permission-mismatch');\n }\n }\n\n // Check geolocation permission if available\n try {\n const geoStatus = await navigator.permissions.query({ name: 'geolocation' });\n // In automation, geolocation is often pre-denied without user action\n if (geoStatus.state === 'denied' && window.outerWidth === 0) {\n anomalies.push('geo-denied-headless');\n }\n } catch (e) {\n // Geolocation permission query may not be supported\n }\n\n // Check if permission.query throws on valid permission\n try {\n await navigator.permissions.query({ name: 'camera' });\n } catch (e) {\n // Some headless browsers don't support camera permission\n if (e.name === 'TypeError') {\n anomalies.push('camera-permission-error');\n }\n }\n\n } catch (e) {\n // If permissions query throws unexpectedly, that's suspicious\n if (e.name !== 'TypeError') {\n anomalies.push('permissions-query-error');\n }\n }\n\n const triggered = anomalies.length > 0;\n const confidence = Math.min(1, anomalies.length * 0.4);\n\n return this.createResult(triggered, { anomalies }, confidence);\n }\n}\n\nexport { PermissionsSignal };\n", "/**\n * @fileoverview Detects non-human mouse movement patterns.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Tracks and analyzes mouse movement patterns.\n * Bots often have perfectly linear paths, no movement, or teleportation.\n */\nclass MouseMovementSignal extends Signal {\n static id = 'mouse-movement';\n static category = 'behavior';\n static weight = 0.9;\n static description = 'Detects non-human mouse movement patterns';\n static requiresInteraction = true;\n\n constructor(options = {}) {\n super(options);\n this._movements = [];\n this._isTracking = false;\n this._trackingDuration = options.trackingDuration || 3000; // Default 3 seconds\n this._minMovements = options.minMovements || 5;\n this._boundHandler = null;\n }\n\n /**\n * Start tracking mouse movements.\n * @returns {Promise<void>}\n */\n startTracking() {\n if (this._isTracking) return;\n \n this._movements = [];\n this._isTracking = true;\n \n this._boundHandler = (e) => {\n this._movements.push({\n x: e.clientX,\n y: e.clientY,\n t: performance.now(),\n });\n };\n \n document.addEventListener('mousemove', this._boundHandler, { passive: true });\n }\n\n /**\n * Stop tracking mouse movements.\n */\n stopTracking() {\n if (!this._isTracking) return;\n \n this._isTracking = false;\n if (this._boundHandler) {\n document.removeEventListener('mousemove', this._boundHandler);\n this._boundHandler = null;\n }\n }\n\n async detect() {\n const anomalies = [];\n let confidence = 0;\n\n // If no tracking has occurred, check if we have movement data\n if (this._movements.length === 0) {\n // Start tracking for a period, then analyze\n this.startTracking();\n \n await new Promise(resolve => setTimeout(resolve, this._trackingDuration));\n \n this.stopTracking();\n }\n\n const movements = this._movements;\n\n // No mouse movements detected\n if (movements.length < this._minMovements) {\n anomalies.push('no-mouse-movement');\n confidence = Math.max(confidence, 0.6);\n return this.createResult(true, { anomalies, movements: movements.length }, confidence);\n }\n\n // Analyze movement patterns\n const analysis = this._analyzeMovements(movements);\n\n // Check for teleportation (large instant jumps)\n if (analysis.teleportCount > 0) {\n anomalies.push('mouse-teleportation');\n confidence = Math.max(confidence, 0.7);\n }\n\n // Check for perfect linear paths\n if (analysis.linearPathRatio > 0.9) {\n anomalies.push('linear-path');\n confidence = Math.max(confidence, 0.8);\n }\n\n // Check for constant velocity (too perfect)\n if (analysis.velocityVariance < 0.01 && movements.length > 10) {\n anomalies.push('constant-velocity');\n confidence = Math.max(confidence, 0.7);\n }\n\n // Check for zero acceleration changes\n if (analysis.accelerationChanges === 0 && movements.length > 10) {\n anomalies.push('no-acceleration-variance');\n confidence = Math.max(confidence, 0.6);\n }\n\n // Check for robotic timing (perfect intervals)\n if (analysis.timingVariance < 1 && movements.length > 10) {\n anomalies.push('robotic-timing');\n confidence = Math.max(confidence, 0.8);\n }\n\n const triggered = anomalies.length > 0;\n\n return this.createResult(triggered, {\n anomalies,\n movementCount: movements.length,\n analysis,\n }, confidence);\n }\n\n /**\n * Analyze movement patterns for anomalies.\n * @param {Array} movements - Array of movement points\n * @returns {Object} Analysis results\n */\n _analyzeMovements(movements) {\n if (movements.length < 3) {\n return {\n teleportCount: 0,\n linearPathRatio: 0,\n velocityVariance: 0,\n accelerationChanges: 0,\n timingVariance: 0,\n };\n }\n\n let teleportCount = 0;\n const velocities = [];\n const angles = [];\n const timeIntervals = [];\n\n for (let i = 1; i < movements.length; i++) {\n const prev = movements[i - 1];\n const curr = movements[i];\n \n const dx = curr.x - prev.x;\n const dy = curr.y - prev.y;\n const dt = curr.t - prev.t;\n \n if (dt === 0) continue;\n \n const distance = Math.sqrt(dx * dx + dy * dy);\n const velocity = distance / dt;\n \n velocities.push(velocity);\n angles.push(Math.atan2(dy, dx));\n timeIntervals.push(dt);\n\n // Teleportation: large jump in very short time\n if (distance > 300 && dt < 10) {\n teleportCount++;\n }\n }\n\n // Calculate velocity variance\n const avgVelocity = velocities.reduce((a, b) => a + b, 0) / velocities.length;\n const velocityVariance = velocities.reduce((acc, v) => \n acc + Math.pow(v - avgVelocity, 2), 0) / velocities.length;\n\n // Calculate angle consistency (linear path detection)\n let angleConsistency = 0;\n if (angles.length > 1) {\n let consistentAngles = 0;\n for (let i = 1; i < angles.length; i++) {\n const angleDiff = Math.abs(angles[i] - angles[i - 1]);\n if (angleDiff < 0.1) consistentAngles++;\n }\n angleConsistency = consistentAngles / (angles.length - 1);\n }\n\n // Calculate timing variance\n const avgInterval = timeIntervals.reduce((a, b) => a + b, 0) / timeIntervals.length;\n const timingVariance = timeIntervals.reduce((acc, t) => \n acc + Math.pow(t - avgInterval, 2), 0) / timeIntervals.length;\n\n // Count acceleration changes\n let accelerationChanges = 0;\n for (let i = 1; i < velocities.length; i++) {\n if ((velocities[i] - velocities[i - 1]) * (velocities[i - 1] - (velocities[i - 2] || 0)) < 0) {\n accelerationChanges++;\n }\n }\n\n return {\n teleportCount,\n linearPathRatio: angleConsistency,\n velocityVariance,\n accelerationChanges,\n timingVariance,\n };\n }\n\n reset() {\n super.reset();\n this.stopTracking();\n this._movements = [];\n }\n}\n\nexport { MouseMovementSignal };\n", "/**\n * @fileoverview Detects non-human keyboard input patterns.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Analyzes keystroke timing patterns.\n * Bots often type with unnatural consistency or inhuman speeds.\n */\nclass KeyboardPatternSignal extends Signal {\n static id = 'keyboard-pattern';\n static category = 'behavior';\n static weight = 0.8;\n static description = 'Detects non-human keystroke patterns';\n static requiresInteraction = true;\n\n constructor(options = {}) {\n super(options);\n this._keystrokes = [];\n this._isTracking = false;\n this._trackingDuration = options.trackingDuration || 5000;\n this._minKeystrokes = options.minKeystrokes || 10;\n this._boundKeydownHandler = null;\n this._boundKeyupHandler = null;\n }\n\n /**\n * Start tracking keyboard events.\n */\n startTracking() {\n if (this._isTracking) return;\n \n this._keystrokes = [];\n this._isTracking = true;\n \n this._boundKeydownHandler = (e) => {\n this._keystrokes.push({\n type: 'down',\n key: e.key,\n code: e.code,\n t: performance.now(),\n });\n };\n\n this._boundKeyupHandler = (e) => {\n this._keystrokes.push({\n type: 'up',\n key: e.key,\n code: e.code,\n t: performance.now(),\n });\n };\n \n document.addEventListener('keydown', this._boundKeydownHandler, { passive: true });\n document.addEventListener('keyup', this._boundKeyupHandler, { passive: true });\n }\n\n /**\n * Stop tracking keyboard events.\n */\n stopTracking() {\n if (!this._isTracking) return;\n \n this._isTracking = false;\n if (this._boundKeydownHandler) {\n document.removeEventListener('keydown', this._boundKeydownHandler);\n this._boundKeydownHandler = null;\n }\n if (this._boundKeyupHandler) {\n document.removeEventListener('keyup', this._boundKeyupHandler);\n this._boundKeyupHandler = null;\n }\n }\n\n async detect() {\n const anomalies = [];\n let confidence = 0;\n\n // If no tracking has occurred, start it\n if (this._keystrokes.length === 0) {\n this.startTracking();\n await new Promise(resolve => setTimeout(resolve, this._trackingDuration));\n this.stopTracking();\n }\n\n const keystrokes = this._keystrokes;\n const keydowns = keystrokes.filter(k => k.type === 'down');\n\n // No keyboard activity\n if (keydowns.length < this._minKeystrokes) {\n // Not necessarily a bot - could just be no typing needed\n return this.createResult(false, { \n reason: 'insufficient-data',\n keystrokes: keydowns.length \n }, 0);\n }\n\n const analysis = this._analyzeKeystrokes(keystrokes);\n\n // Check for inhuman typing speed (> 20 chars/second sustained)\n if (analysis.avgInterKeystrokeTime < 50 && keydowns.length > 20) {\n anomalies.push('inhuman-speed');\n confidence = Math.max(confidence, 0.9);\n }\n\n // Check for too-consistent timing (robotic)\n if (analysis.timingVariance < 5 && keydowns.length > 15) {\n anomalies.push('robotic-timing');\n confidence = Math.max(confidence, 0.8);\n }\n\n // Check for missing key-up events (programmatic input)\n if (analysis.missingKeyups > keydowns.length * 0.5) {\n anomalies.push('missing-keyups');\n confidence = Math.max(confidence, 0.7);\n }\n\n // Check for perfect key hold times\n if (analysis.holdTimeVariance < 2 && analysis.holdTimes.length > 10) {\n anomalies.push('constant-hold-time');\n confidence = Math.max(confidence, 0.6);\n }\n\n // Check for sequential key codes (batch input)\n if (analysis.sequentialKeys > keydowns.length * 0.8 && keydowns.length > 10) {\n anomalies.push('sequential-input');\n confidence = Math.max(confidence, 0.5);\n }\n\n // Check for no typing rhythm variation\n if (analysis.rhythmScore < 0.1 && keydowns.length > 20) {\n anomalies.push('no-rhythm-variation');\n confidence = Math.max(confidence, 0.6);\n }\n\n const triggered = anomalies.length > 0;\n\n return this.createResult(triggered, {\n anomalies,\n keystrokeCount: keydowns.length,\n analysis,\n }, confidence);\n }\n\n /**\n * Analyze keystroke patterns.\n * @param {Array} keystrokes - Array of keystroke events\n * @returns {Object} Analysis results\n */\n _analyzeKeystrokes(keystrokes) {\n const keydowns = keystrokes.filter(k => k.type === 'down');\n const keyups = keystrokes.filter(k => k.type === 'up');\n\n if (keydowns.length < 2) {\n return {\n avgInterKeystrokeTime: Infinity,\n timingVariance: Infinity,\n missingKeyups: 0,\n holdTimeVariance: Infinity,\n holdTimes: [],\n sequentialKeys: 0,\n rhythmScore: 1,\n };\n }\n\n // Calculate inter-keystroke times\n const interTimes = [];\n for (let i = 1; i < keydowns.length; i++) {\n interTimes.push(keydowns[i].t - keydowns[i - 1].t);\n }\n\n const avgInterKeystrokeTime = interTimes.reduce((a, b) => a + b, 0) / interTimes.length;\n const timingVariance = interTimes.reduce((acc, t) => \n acc + Math.pow(t - avgInterKeystrokeTime, 2), 0) / interTimes.length;\n\n // Calculate hold times (time between keydown and keyup for same key)\n const holdTimes = [];\n for (const down of keydowns) {\n const up = keyups.find(u => u.key === down.key && u.t > down.t);\n if (up) {\n holdTimes.push(up.t - down.t);\n }\n }\n\n const avgHoldTime = holdTimes.length > 0 \n ? holdTimes.reduce((a, b) => a + b, 0) / holdTimes.length \n : 0;\n const holdTimeVariance = holdTimes.length > 0\n ? holdTimes.reduce((acc, t) => acc + Math.pow(t - avgHoldTime, 2), 0) / holdTimes.length\n : Infinity;\n\n // Count missing keyups\n const missingKeyups = keydowns.length - holdTimes.length;\n\n // Count sequential keys (chars typed in order, like 'abc' or '123')\n let sequentialKeys = 0;\n for (let i = 1; i < keydowns.length; i++) {\n const prevCode = keydowns[i - 1].key.charCodeAt(0);\n const currCode = keydowns[i].key.charCodeAt(0);\n if (Math.abs(currCode - prevCode) === 1) {\n sequentialKeys++;\n }\n }\n\n // Calculate typing rhythm score (variation in timing patterns)\n // Humans have natural rhythm variations (pause after words, faster for common patterns)\n let rhythmScore = 0;\n if (interTimes.length > 5) {\n const sortedTimes = [...interTimes].sort((a, b) => a - b);\n const median = sortedTimes[Math.floor(sortedTimes.length / 2)];\n // Count how many timings deviate significantly from median\n const deviations = interTimes.filter(t => Math.abs(t - median) > median * 0.3).length;\n rhythmScore = deviations / interTimes.length;\n }\n\n return {\n avgInterKeystrokeTime,\n timingVariance,\n missingKeyups,\n holdTimeVariance,\n holdTimes,\n sequentialKeys,\n rhythmScore,\n };\n }\n\n reset() {\n super.reset();\n this.stopTracking();\n this._keystrokes = [];\n }\n}\n\nexport { KeyboardPatternSignal };\n", "/**\n * @fileoverview Detects suspicious interaction timing patterns.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Measures timing between page load and first interaction.\n * Bots often interact too fast or with perfect timing patterns.\n */\nclass InteractionTimingSignal extends Signal {\n static id = 'interaction-timing';\n static category = 'behavior';\n static weight = 0.6;\n static description = 'Detects suspicious interaction timing';\n static requiresInteraction = true;\n\n constructor(options = {}) {\n super(options);\n this._pageLoadTime = performance.now();\n this._firstInteractionTime = null;\n this._interactions = [];\n this._isTracking = false;\n this._trackingDuration = options.trackingDuration || 5000;\n this._boundHandler = null;\n }\n\n /**\n * Start tracking interactions.\n */\n startTracking() {\n if (this._isTracking) return;\n \n this._interactions = [];\n this._isTracking = true;\n \n const interactionEvents = ['click', 'mousedown', 'touchstart', 'keydown', 'scroll'];\n \n this._boundHandler = (e) => {\n const now = performance.now();\n if (this._firstInteractionTime === null) {\n this._firstInteractionTime = now;\n }\n this._interactions.push({\n type: e.type,\n t: now,\n timeSinceLoad: now - this._pageLoadTime,\n });\n };\n \n for (const event of interactionEvents) {\n document.addEventListener(event, this._boundHandler, { passive: true, capture: true });\n }\n }\n\n /**\n * Stop tracking interactions.\n */\n stopTracking() {\n if (!this._isTracking) return;\n \n this._isTracking = false;\n const interactionEvents = ['click', 'mousedown', 'touchstart', 'keydown', 'scroll'];\n \n if (this._boundHandler) {\n for (const event of interactionEvents) {\n document.removeEventListener(event, this._boundHandler, { capture: true });\n }\n this._boundHandler = null;\n }\n }\n\n async detect() {\n const anomalies = [];\n let confidence = 0;\n\n // Start tracking if not already\n if (!this._isTracking && this._interactions.length === 0) {\n this.startTracking();\n await new Promise(resolve => setTimeout(resolve, this._trackingDuration));\n this.stopTracking();\n }\n\n const interactions = this._interactions;\n\n // No interactions - not necessarily suspicious, could be passive viewing\n if (interactions.length === 0) {\n return this.createResult(false, { \n reason: 'no-interactions',\n }, 0);\n }\n\n // Check time to first interaction\n const firstInteraction = interactions[0];\n \n // Suspiciously fast first interaction (< 100ms after page load)\n if (firstInteraction.timeSinceLoad < 100) {\n anomalies.push('instant-interaction');\n confidence = Math.max(confidence, 0.9);\n }\n // Very fast interaction (< 300ms)\n else if (firstInteraction.timeSinceLoad < 300) {\n anomalies.push('very-fast-interaction');\n confidence = Math.max(confidence, 0.6);\n }\n\n // Analyze interaction intervals\n if (interactions.length > 3) {\n const intervals = [];\n for (let i = 1; i < interactions.length; i++) {\n intervals.push(interactions[i].t - interactions[i - 1].t);\n }\n\n const avgInterval = intervals.reduce((a, b) => a + b, 0) / intervals.length;\n const variance = intervals.reduce((acc, t) => \n acc + Math.pow(t - avgInterval, 2), 0) / intervals.length;\n\n // Perfectly timed intervals (robotic)\n if (variance < 10 && interactions.length > 5) {\n anomalies.push('robotic-intervals');\n confidence = Math.max(confidence, 0.8);\n }\n\n // Check for burst interactions (many in short time)\n const burstThreshold = 50; // ms\n let burstCount = 0;\n for (const interval of intervals) {\n if (interval < burstThreshold) burstCount++;\n }\n if (burstCount > intervals.length * 0.7) {\n anomalies.push('burst-interactions');\n confidence = Math.max(confidence, 0.7);\n }\n }\n\n // Check interaction sequence (bots often follow predictable patterns)\n const typeSequence = interactions.map(i => i.type).join(',');\n \n // Repeated identical sequences\n if (interactions.length >= 6) {\n const halfLength = Math.floor(interactions.length / 2);\n const firstHalf = interactions.slice(0, halfLength).map(i => i.type).join(',');\n const secondHalf = interactions.slice(halfLength, halfLength * 2).map(i => i.type).join(',');\n \n if (firstHalf === secondHalf && firstHalf.length > 0) {\n anomalies.push('repeated-sequence');\n confidence = Math.max(confidence, 0.6);\n }\n }\n\n const triggered = anomalies.length > 0;\n\n return this.createResult(triggered, {\n anomalies,\n interactionCount: interactions.length,\n timeToFirstInteraction: firstInteraction.timeSinceLoad,\n firstInteractionType: firstInteraction.type,\n }, confidence);\n }\n\n reset() {\n super.reset();\n this.stopTracking();\n this._pageLoadTime = performance.now();\n this._firstInteractionTime = null;\n this._interactions = [];\n }\n}\n\nexport { InteractionTimingSignal };\n", "/**\n * @fileoverview Detects non-human scroll patterns.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Tracks and analyzes scroll behavior patterns.\n * Detects programmatic scrolling and non-human scroll patterns.\n */\nclass ScrollBehaviorSignal extends Signal {\n static id = 'scroll-behavior';\n static category = 'behavior';\n static weight = 0.5;\n static description = 'Detects programmatic scroll patterns';\n static requiresInteraction = true;\n\n constructor(options = {}) {\n super(options);\n this._scrollEvents = [];\n this._isTracking = false;\n this._trackingDuration = options.trackingDuration || 3000;\n this._boundHandler = null;\n }\n\n /**\n * Start tracking scroll events.\n */\n startTracking() {\n if (this._isTracking) return;\n \n this._scrollEvents = [];\n this._isTracking = true;\n \n this._boundHandler = () => {\n this._scrollEvents.push({\n scrollY: window.scrollY,\n scrollX: window.scrollX,\n t: performance.now(),\n });\n };\n \n window.addEventListener('scroll', this._boundHandler, { passive: true });\n }\n\n /**\n * Stop tracking scroll events.\n */\n stopTracking() {\n if (!this._isTracking) return;\n \n this._isTracking = false;\n if (this._boundHandler) {\n window.removeEventListener('scroll', this._boundHandler);\n this._boundHandler = null;\n }\n }\n\n async detect() {\n const anomalies = [];\n let confidence = 0;\n\n // Start tracking if needed\n if (this._scrollEvents.length === 0) {\n this.startTracking();\n await new Promise(resolve => setTimeout(resolve, this._trackingDuration));\n this.stopTracking();\n }\n\n const events = this._scrollEvents;\n\n // No scroll events - not necessarily suspicious\n if (events.length < 3) {\n return this.createResult(false, {\n reason: 'insufficient-scroll-data',\n scrollEvents: events.length,\n }, 0);\n }\n\n const analysis = this._analyzeScrollPatterns(events);\n\n // Check for instant jumps (scrollTo without animation)\n if (analysis.instantJumps > 0) {\n anomalies.push('instant-scroll-jumps');\n confidence = Math.max(confidence, 0.7);\n }\n\n // Check for perfectly consistent scroll speed\n if (analysis.velocityVariance < 0.1 && events.length > 10) {\n anomalies.push('constant-scroll-velocity');\n confidence = Math.max(confidence, 0.6);\n }\n\n // Check for no momentum (instant stops)\n if (analysis.momentumEvents === 0 && events.length > 5) {\n anomalies.push('no-scroll-momentum');\n confidence = Math.max(confidence, 0.5);\n }\n\n // Check for perfectly even scroll intervals\n if (analysis.intervalVariance < 5 && events.length > 10) {\n anomalies.push('robotic-scroll-timing');\n confidence = Math.max(confidence, 0.7);\n }\n\n // Check for exclusively vertical or horizontal scroll\n if (analysis.scrollDirections === 1 && Math.abs(analysis.totalScrollY) > 1000) {\n // Could be normal, but combined with other factors is suspicious\n if (analysis.velocityVariance < 1) {\n anomalies.push('one-dimensional-scroll');\n confidence = Math.max(confidence, 0.4);\n }\n }\n\n // Check for scroll-to-element patterns (exact positions)\n if (analysis.exactPositionScrolls > 2) {\n anomalies.push('exact-position-scrolls');\n confidence = Math.max(confidence, 0.6);\n }\n\n const triggered = anomalies.length > 0;\n\n return this.createResult(triggered, {\n anomalies,\n scrollEventCount: events.length,\n analysis,\n }, confidence);\n }\n\n /**\n * Analyze scroll patterns for anomalies.\n * @param {Array} events - Array of scroll events\n * @returns {Object} Analysis results\n */\n _analyzeScrollPatterns(events) {\n if (events.length < 2) {\n return {\n instantJumps: 0,\n velocityVariance: 0,\n momentumEvents: 0,\n intervalVariance: 0,\n scrollDirections: 0,\n totalScrollY: 0,\n exactPositionScrolls: 0,\n };\n }\n\n let instantJumps = 0;\n let momentumEvents = 0;\n const velocities = [];\n const intervals = [];\n let hasVertical = false;\n let hasHorizontal = false;\n let exactPositionScrolls = 0;\n\n // Common scroll targets (element heights, percentages)\n const commonPositions = [0, 100, 200, 300, 400, 500, 600, 800, 1000];\n\n for (let i = 1; i < events.length; i++) {\n const prev = events[i - 1];\n const curr = events[i];\n \n const dy = curr.scrollY - prev.scrollY;\n const dx = curr.scrollX - prev.scrollX;\n const dt = curr.t - prev.t;\n \n intervals.push(dt);\n\n if (Math.abs(dy) > 0) hasVertical = true;\n if (Math.abs(dx) > 0) hasHorizontal = true;\n\n if (dt === 0) continue;\n\n const velocity = Math.sqrt(dy * dy + dx * dx) / dt;\n velocities.push(velocity);\n\n // Instant jump: large distance in very short time (< 16ms, one frame)\n const distance = Math.abs(dy) + Math.abs(dx);\n if (distance > 200 && dt < 20) {\n instantJumps++;\n }\n\n // Momentum: decreasing velocity (natural scroll deceleration)\n if (i > 1 && velocities.length > 1) {\n const prevVelocity = velocities[velocities.length - 2];\n if (velocity < prevVelocity * 0.9 && velocity > 0) {\n momentumEvents++;\n }\n }\n\n // Check for exact positions\n if (commonPositions.includes(Math.round(curr.scrollY))) {\n exactPositionScrolls++;\n }\n }\n\n // Calculate velocity variance\n const avgVelocity = velocities.length > 0 \n ? velocities.reduce((a, b) => a + b, 0) / velocities.length \n : 0;\n const velocityVariance = velocities.length > 0\n ? velocities.reduce((acc, v) => acc + Math.pow(v - avgVelocity, 2), 0) / velocities.length\n : 0;\n\n // Calculate interval variance\n const avgInterval = intervals.reduce((a, b) => a + b, 0) / intervals.length;\n const intervalVariance = intervals.reduce((acc, t) => \n acc + Math.pow(t - avgInterval, 2), 0) / intervals.length;\n\n // Count scroll directions\n let scrollDirections = 0;\n if (hasVertical) scrollDirections++;\n if (hasHorizontal) scrollDirections++;\n\n // Total scroll distance\n const totalScrollY = events[events.length - 1].scrollY - events[0].scrollY;\n\n return {\n instantJumps,\n velocityVariance,\n momentumEvents,\n intervalVariance,\n scrollDirections,\n totalScrollY,\n exactPositionScrolls,\n };\n }\n\n reset() {\n super.reset();\n this.stopTracking();\n this._scrollEvents = [];\n }\n}\n\nexport { ScrollBehaviorSignal };\n", "/**\n * @fileoverview Detects browser plugin anomalies.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Checks for empty or suspicious plugin configurations.\n * Headless browsers and bots often have no plugins.\n */\nclass PluginsSignal extends Signal {\n static id = 'plugins';\n static category = 'fingerprint';\n static weight = 0.6;\n static description = 'Detects browser plugin anomalies';\n\n async detect() {\n const anomalies = [];\n let confidence = 0;\n\n const plugins = navigator.plugins;\n const mimeTypes = navigator.mimeTypes;\n\n // Check if plugins exists\n if (!plugins) {\n anomalies.push('no-plugins-object');\n confidence = Math.max(confidence, 0.6);\n return this.createResult(true, { anomalies }, confidence);\n }\n\n // Check for empty plugins array\n if (plugins.length === 0) {\n anomalies.push('empty-plugins');\n confidence = Math.max(confidence, 0.5);\n }\n\n // Check for Chrome-specific plugins in Chrome browser\n const ua = navigator.userAgent || '';\n if (ua.includes('Chrome') && !ua.includes('Chromium')) {\n // Real Chrome typically has at least these plugins\n const hasChromePdf = Array.from(plugins).some(p => \n p.name.includes('PDF') || p.name.includes('Chromium PDF'));\n \n if (!hasChromePdf && plugins.length === 0) {\n anomalies.push('chrome-missing-pdf-plugin');\n confidence = Math.max(confidence, 0.4);\n }\n }\n\n // Check for consistent plugin/mimeType relationship\n if (plugins.length > 0 && mimeTypes) {\n let totalMimeTypes = 0;\n for (let i = 0; i < plugins.length; i++) {\n totalMimeTypes += plugins[i].length || 0;\n }\n\n // Plugins exist but no mimeTypes\n if (mimeTypes.length === 0 && totalMimeTypes > 0) {\n anomalies.push('mimetypes-mismatch');\n confidence = Math.max(confidence, 0.5);\n }\n }\n\n // Check for identical plugin names (sign of spoofing)\n if (plugins.length > 1) {\n const names = Array.from(plugins).map(p => p.name);\n const uniqueNames = new Set(names);\n if (uniqueNames.size < names.length) {\n anomalies.push('duplicate-plugins');\n confidence = Math.max(confidence, 0.6);\n }\n }\n\n // Check for plugin array tampering\n try {\n const desc = Object.getOwnPropertyDescriptor(Navigator.prototype, 'plugins');\n if (desc && desc.get) {\n // Check if it's been overridden\n const nativeToString = desc.get.toString();\n if (!nativeToString.includes('[native code]')) {\n anomalies.push('plugins-getter-overridden');\n confidence = Math.max(confidence, 0.7);\n }\n }\n } catch (e) {\n // Ignore errors during introspection\n }\n\n // Check for suspiciously few plugins in a desktop browser\n const isMobile = /Android|iPhone|iPad|iPod|Mobile/i.test(ua);\n if (!isMobile && plugins.length === 1) {\n anomalies.push('minimal-plugins');\n confidence = Math.max(confidence, 0.3);\n }\n\n const triggered = anomalies.length > 0;\n\n return this.createResult(triggered, {\n anomalies,\n pluginCount: plugins.length,\n mimeTypeCount: mimeTypes?.length || 0,\n }, confidence);\n }\n}\n\nexport { PluginsSignal };\n", "/**\n * @fileoverview Detects WebGL rendering anomalies.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Detects WebGL anomalies and spoofed renderer information.\n * Bots often have missing, disabled, or fake WebGL contexts.\n */\nclass WebGLSignal extends Signal {\n static id = 'webgl';\n static category = 'fingerprint';\n static weight = 0.7;\n static description = 'Detects WebGL rendering anomalies';\n\n async detect() {\n const anomalies = [];\n let confidence = 0;\n\n // Try to get WebGL context\n const canvas = document.createElement('canvas');\n let gl = null;\n\n try {\n gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\n } catch (e) {\n anomalies.push('webgl-error');\n confidence = Math.max(confidence, 0.5);\n }\n\n if (!gl) {\n // WebGL not available - could be disabled or blocked\n anomalies.push('webgl-unavailable');\n confidence = Math.max(confidence, 0.4);\n return this.createResult(true, { anomalies }, confidence);\n }\n\n // Get renderer info\n const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');\n let vendor = '';\n let renderer = '';\n\n if (debugInfo) {\n vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) || '';\n renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) || '';\n }\n\n // Check for empty renderer info (common in headless)\n if (!vendor && !renderer) {\n anomalies.push('no-webgl-renderer-info');\n confidence = Math.max(confidence, 0.6);\n }\n\n // Check for known headless/virtual renderer strings\n const suspiciousRenderers = [\n 'swiftshader',\n 'llvmpipe',\n 'software',\n 'mesa',\n 'google swiftshader',\n 'vmware',\n 'virtualbox',\n ];\n\n const rendererLower = renderer.toLowerCase();\n for (const sus of suspiciousRenderers) {\n if (rendererLower.includes(sus)) {\n anomalies.push(`suspicious-renderer-${sus.replace(/\\s+/g, '-')}`);\n confidence = Math.max(confidence, 0.7);\n break;\n }\n }\n\n // Check for mismatched vendor/renderer\n if (vendor && renderer) {\n // NVIDIA renderer should have NVIDIA vendor\n if (rendererLower.includes('nvidia') && !vendor.toLowerCase().includes('nvidia')) {\n anomalies.push('vendor-renderer-mismatch');\n confidence = Math.max(confidence, 0.6);\n }\n // AMD renderer should have AMD/ATI vendor\n if ((rendererLower.includes('amd') || rendererLower.includes('radeon')) && \n !vendor.toLowerCase().includes('amd') && !vendor.toLowerCase().includes('ati')) {\n anomalies.push('vendor-renderer-mismatch');\n confidence = Math.max(confidence, 0.6);\n }\n }\n\n // Check for supported extensions\n const extensions = gl.getSupportedExtensions() || [];\n \n // Suspiciously few extensions\n if (extensions.length < 5) {\n anomalies.push('few-webgl-extensions');\n confidence = Math.max(confidence, 0.4);\n }\n\n // Check for WebGL parameter consistency\n const maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);\n const maxViewportDims = gl.getParameter(gl.MAX_VIEWPORT_DIMS);\n\n // Unrealistic values\n if (maxTextureSize < 1024 || maxTextureSize > 65536) {\n anomalies.push('unrealistic-max-texture');\n confidence = Math.max(confidence, 0.5);\n }\n\n // Check if WebGL rendering actually works\n try {\n // Simple render test\n gl.clearColor(0.0, 0.0, 0.0, 1.0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n \n const pixels = new Uint8Array(4);\n gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);\n \n // If clear didn't work, something's wrong\n if (pixels[3] !== 255) {\n anomalies.push('webgl-render-failure');\n confidence = Math.max(confidence, 0.6);\n }\n } catch (e) {\n anomalies.push('webgl-render-error');\n confidence = Math.max(confidence, 0.5);\n }\n\n // Clean up\n const loseContext = gl.getExtension('WEBGL_lose_context');\n if (loseContext) {\n loseContext.loseContext();\n }\n\n const triggered = anomalies.length > 0;\n\n return this.createResult(triggered, {\n anomalies,\n vendor,\n renderer,\n extensionCount: extensions.length,\n maxTextureSize,\n }, confidence);\n }\n}\n\nexport { WebGLSignal };\n", "/**\n * @fileoverview Detects canvas fingerprint blocking or spoofing.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Detects canvas manipulation, blocking, or spoofing.\n * Privacy tools and some bots modify canvas output.\n */\nclass CanvasSignal extends Signal {\n static id = 'canvas';\n static category = 'fingerprint';\n static weight = 0.5;\n static description = 'Detects canvas fingerprint anomalies';\n\n async detect() {\n const anomalies = [];\n let confidence = 0;\n\n try {\n const canvas = document.createElement('canvas');\n canvas.width = 200;\n canvas.height = 50;\n \n const ctx = canvas.getContext('2d');\n if (!ctx) {\n anomalies.push('canvas-context-unavailable');\n confidence = Math.max(confidence, 0.5);\n return this.createResult(true, { anomalies }, confidence);\n }\n\n // Draw a complex pattern for fingerprinting\n ctx.textBaseline = 'alphabetic';\n ctx.font = '14px Arial';\n ctx.fillStyle = '#f60';\n ctx.fillRect(0, 0, 200, 50);\n ctx.fillStyle = '#069';\n ctx.fillText('Bot Detection Test \uD83E\uDD16', 2, 15);\n ctx.fillStyle = 'rgba(102, 204, 0, 0.7)';\n ctx.fillText('Canvas Fingerprint', 4, 30);\n \n // Add some complex graphics\n ctx.beginPath();\n ctx.arc(100, 25, 10, 0, Math.PI * 2, true);\n ctx.closePath();\n ctx.fill();\n\n // Get data URL\n const dataUrl1 = canvas.toDataURL();\n\n // Draw again - should produce same result\n ctx.clearRect(0, 0, 200, 50);\n ctx.fillStyle = '#f60';\n ctx.fillRect(0, 0, 200, 50);\n ctx.fillStyle = '#069';\n ctx.fillText('Bot Detection Test \uD83E\uDD16', 2, 15);\n ctx.fillStyle = 'rgba(102, 204, 0, 0.7)';\n ctx.fillText('Canvas Fingerprint', 4, 30);\n ctx.beginPath();\n ctx.arc(100, 25, 10, 0, Math.PI * 2, true);\n ctx.closePath();\n ctx.fill();\n\n const dataUrl2 = canvas.toDataURL();\n\n // If results differ, canvas is being randomized (privacy protection)\n if (dataUrl1 !== dataUrl2) {\n anomalies.push('canvas-randomized');\n confidence = Math.max(confidence, 0.6);\n }\n\n // Check for blank canvas (blocking)\n if (dataUrl1.length < 1000) {\n anomalies.push('canvas-possibly-blank');\n confidence = Math.max(confidence, 0.4);\n }\n\n // Check for common blocked canvas signature\n const blankCanvas = document.createElement('canvas');\n blankCanvas.width = 200;\n blankCanvas.height = 50;\n const blankUrl = blankCanvas.toDataURL();\n \n if (dataUrl1 === blankUrl) {\n anomalies.push('canvas-rendering-blocked');\n confidence = Math.max(confidence, 0.7);\n }\n\n // Check for toDataURL being overridden\n try {\n const toDataURLStr = canvas.toDataURL.toString();\n if (!toDataURLStr.includes('[native code]')) {\n anomalies.push('toDataURL-overridden');\n confidence = Math.max(confidence, 0.8);\n }\n } catch (e) {\n // Some environments may throw\n }\n\n // Check pixel data directly\n const imageData = ctx.getImageData(0, 0, 200, 50);\n const pixels = imageData.data;\n \n // Check if all pixels are the same (completely blocked)\n let allSame = true;\n const firstPixel = [pixels[0], pixels[1], pixels[2], pixels[3]];\n for (let i = 4; i < pixels.length; i += 4) {\n if (pixels[i] !== firstPixel[0] || \n pixels[i+1] !== firstPixel[1] || \n pixels[i+2] !== firstPixel[2]) {\n allSame = false;\n break;\n }\n }\n \n if (allSame) {\n anomalies.push('uniform-pixel-data');\n confidence = Math.max(confidence, 0.6);\n }\n\n } catch (e) {\n anomalies.push('canvas-error');\n confidence = Math.max(confidence, 0.4);\n }\n\n const triggered = anomalies.length > 0;\n\n return this.createResult(triggered, { anomalies }, confidence);\n }\n}\n\nexport { CanvasSignal };\n", "/**\n * @fileoverview Detects AudioContext anomalies.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Checks for AudioContext anomalies.\n * Bots and headless browsers often have unusual or missing audio capabilities.\n */\nclass AudioContextSignal extends Signal {\n static id = 'audio-context';\n static category = 'fingerprint';\n static weight = 0.5;\n static description = 'Detects AudioContext anomalies';\n\n async detect() {\n const anomalies = [];\n let confidence = 0;\n\n // Check if AudioContext exists\n const AudioContext = window.AudioContext || window.webkitAudioContext;\n \n if (!AudioContext) {\n // AudioContext not available\n anomalies.push('audio-context-unavailable');\n confidence = Math.max(confidence, 0.4);\n return this.createResult(true, { anomalies }, confidence);\n }\n\n let audioContext = null;\n let oscillator = null;\n let analyser = null;\n\n try {\n audioContext = new AudioContext();\n \n // Check sample rate - unusual values may indicate virtualization\n const sampleRate = audioContext.sampleRate;\n if (sampleRate !== 44100 && sampleRate !== 48000 && sampleRate !== 96000) {\n anomalies.push('unusual-sample-rate');\n confidence = Math.max(confidence, 0.3);\n }\n\n // Check for suspended state (auto-play policy)\n // This is normal, but combined with other factors can be suspicious\n\n // Try to create an oscillator and check its properties\n oscillator = audioContext.createOscillator();\n analyser = audioContext.createAnalyser();\n \n if (!oscillator || !analyser) {\n anomalies.push('audio-nodes-unavailable');\n confidence = Math.max(confidence, 0.5);\n } else {\n // Check analyser properties\n const fftSize = analyser.fftSize;\n if (fftSize !== 2048) {\n // Non-default value might indicate tampering\n // but this alone isn't conclusive\n }\n\n // Check destination\n const destination = audioContext.destination;\n if (!destination || destination.maxChannelCount === 0) {\n anomalies.push('no-audio-destination');\n confidence = Math.max(confidence, 0.6);\n }\n\n // Check for channel count\n if (destination && destination.maxChannelCount < 2) {\n anomalies.push('mono-audio-only');\n confidence = Math.max(confidence, 0.3);\n }\n }\n\n // Check for overridden AudioContext\n try {\n const audioCtxStr = AudioContext.toString();\n if (!audioCtxStr.includes('[native code]')) {\n anomalies.push('audio-context-overridden');\n confidence = Math.max(confidence, 0.7);\n }\n } catch (e) {\n // Some environments may throw\n }\n\n // Audio fingerprint test - create a noise signal and check output\n try {\n if (audioContext.state === 'suspended') {\n // Try to resume (may not work without user gesture)\n await audioContext.resume().catch(() => {});\n }\n\n // Only perform if we can\n if (audioContext.state === 'running') {\n const oscillatorNode = audioContext.createOscillator();\n const gainNode = audioContext.createGain();\n const scriptProcessor = audioContext.createScriptProcessor \n ? audioContext.createScriptProcessor(4096, 1, 1)\n : null;\n\n if (scriptProcessor) {\n oscillatorNode.type = 'triangle';\n oscillatorNode.frequency.value = 10000;\n gainNode.gain.value = 0;\n \n oscillatorNode.connect(gainNode);\n gainNode.connect(scriptProcessor);\n scriptProcessor.connect(audioContext.destination);\n\n // Brief test\n oscillatorNode.start(0);\n \n await new Promise(resolve => setTimeout(resolve, 50));\n \n oscillatorNode.stop();\n oscillatorNode.disconnect();\n gainNode.disconnect();\n scriptProcessor.disconnect();\n }\n }\n } catch (e) {\n // Audio fingerprinting blocked or failed\n anomalies.push('audio-fingerprint-blocked');\n confidence = Math.max(confidence, 0.4);\n }\n\n // Check for OfflineAudioContext\n const OfflineAudioContext = window.OfflineAudioContext || window.webkitOfflineAudioContext;\n if (!OfflineAudioContext) {\n anomalies.push('offline-audio-context-unavailable');\n confidence = Math.max(confidence, 0.3);\n }\n\n } catch (e) {\n anomalies.push('audio-context-error');\n confidence = Math.max(confidence, 0.4);\n } finally {\n // Clean up\n if (oscillator) {\n try { oscillator.disconnect(); } catch (e) {}\n }\n if (analyser) {\n try { analyser.disconnect(); } catch (e) {}\n }\n if (audioContext) {\n try { audioContext.close(); } catch (e) {}\n }\n }\n\n const triggered = anomalies.length > 0;\n\n return this.createResult(triggered, { anomalies }, confidence);\n }\n}\n\nexport { AudioContextSignal };\n", "/**\n * @fileoverview Detects unusual screen and window dimensions.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Detects screen dimension anomalies.\n * Bots and headless browsers often have unusual screen configurations.\n */\nclass ScreenSignal extends Signal {\n static id = 'screen';\n static category = 'fingerprint';\n static weight = 0.4;\n static description = 'Detects unusual screen dimensions';\n\n async detect() {\n const anomalies = [];\n let confidence = 0;\n\n const screen = window.screen;\n if (!screen) {\n anomalies.push('no-screen-object');\n confidence = Math.max(confidence, 0.6);\n return this.createResult(true, { anomalies }, confidence);\n }\n\n const width = screen.width;\n const height = screen.height;\n const availWidth = screen.availWidth;\n const availHeight = screen.availHeight;\n const colorDepth = screen.colorDepth;\n const pixelDepth = screen.pixelDepth;\n const outerWidth = window.outerWidth;\n const outerHeight = window.outerHeight;\n const innerWidth = window.innerWidth;\n const innerHeight = window.innerHeight;\n\n // Check for zero dimensions (headless indicator)\n if (outerWidth === 0 || outerHeight === 0) {\n anomalies.push('zero-outer-dimensions');\n confidence = Math.max(confidence, 0.8);\n }\n\n if (innerWidth === 0 || innerHeight === 0) {\n anomalies.push('zero-inner-dimensions');\n confidence = Math.max(confidence, 0.7);\n }\n\n // Check for very small screen (unrealistic for desktop)\n const ua = navigator.userAgent || '';\n const isMobile = /Android|iPhone|iPad|iPod|Mobile/i.test(ua);\n \n if (!isMobile && (width < 640 || height < 480)) {\n anomalies.push('very-small-screen');\n confidence = Math.max(confidence, 0.5);\n }\n\n // Check for very large screen (unrealistic)\n if (width > 7680 || height > 4320) { // Beyond 8K\n anomalies.push('unrealistic-screen-size');\n confidence = Math.max(confidence, 0.4);\n }\n\n // Check for common headless default dimensions\n const headlessDefaults = [\n { w: 800, h: 600 },\n { w: 1024, h: 768 },\n { w: 1920, h: 1080 },\n ];\n\n for (const def of headlessDefaults) {\n if (width === def.w && height === def.h && \n outerWidth === def.w && outerHeight === def.h) {\n // Exact match with no browser chrome - suspicious\n anomalies.push('headless-default-dimensions');\n confidence = Math.max(confidence, 0.5);\n break;\n }\n }\n\n // Check for screen larger than available (impossible)\n if (availWidth > width || availHeight > height) {\n anomalies.push('available-exceeds-total');\n confidence = Math.max(confidence, 0.7);\n }\n\n // Check for window larger than screen\n if (outerWidth > width || outerHeight > height) {\n anomalies.push('window-exceeds-screen');\n confidence = Math.max(confidence, 0.6);\n }\n\n // Check for unusual color depth\n if (colorDepth !== 24 && colorDepth !== 32 && colorDepth !== 30 && colorDepth !== 48) {\n anomalies.push('unusual-color-depth');\n confidence = Math.max(confidence, 0.3);\n }\n\n // Check for mismatched color/pixel depth\n if (colorDepth !== pixelDepth) {\n anomalies.push('depth-mismatch');\n confidence = Math.max(confidence, 0.3);\n }\n\n // Check for device pixel ratio anomalies\n const dpr = window.devicePixelRatio;\n if (dpr === 0 || dpr === undefined) {\n anomalies.push('missing-device-pixel-ratio');\n confidence = Math.max(confidence, 0.5);\n } else if (dpr < 0.5 || dpr > 5) {\n anomalies.push('unusual-device-pixel-ratio');\n confidence = Math.max(confidence, 0.4);\n }\n\n // Check for screen orientation API anomalies\n if (screen.orientation) {\n const orientationType = screen.orientation.type;\n const orientationAngle = screen.orientation.angle;\n \n // Landscape device with portrait dimensions\n if (orientationType.includes('landscape') && width < height) {\n anomalies.push('orientation-dimension-mismatch');\n confidence = Math.max(confidence, 0.4);\n }\n \n // Portrait device with landscape dimensions\n if (orientationType.includes('portrait') && width > height) {\n anomalies.push('orientation-dimension-mismatch');\n confidence = Math.max(confidence, 0.4);\n }\n }\n\n // Check for innerWidth/Height being exactly equal to outer (no browser chrome)\n if (innerWidth === outerWidth && innerHeight === outerHeight && \n outerWidth > 0 && outerHeight > 0) {\n anomalies.push('no-browser-chrome');\n confidence = Math.max(confidence, 0.5);\n }\n\n const triggered = anomalies.length > 0;\n\n return this.createResult(triggered, {\n anomalies,\n dimensions: {\n screen: { width, height },\n available: { width: availWidth, height: availHeight },\n window: { outer: { width: outerWidth, height: outerHeight }, \n inner: { width: innerWidth, height: innerHeight } },\n colorDepth,\n devicePixelRatio: dpr,\n },\n }, confidence);\n }\n}\n\nexport { ScreenSignal };\n", "/**\n * @fileoverview Detects suspicious page load timing patterns.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Analyzes page load timing for automation indicators.\n * Bots often have unusual or suspiciously fast load patterns.\n */\nclass PageLoadSignal extends Signal {\n static id = 'page-load';\n static category = 'timing';\n static weight = 0.5;\n static description = 'Detects suspicious page load timing';\n\n async detect() {\n const anomalies = [];\n let confidence = 0;\n\n // Check if Performance API is available\n if (!window.performance || !performance.timing) {\n // Try Navigation Timing API Level 2\n if (performance.getEntriesByType) {\n const navEntries = performance.getEntriesByType('navigation');\n if (navEntries.length > 0) {\n return this._analyzeNavigationTiming(navEntries[0]);\n }\n }\n \n anomalies.push('no-performance-api');\n confidence = Math.max(confidence, 0.3);\n return this.createResult(true, { anomalies }, confidence);\n }\n\n const timing = performance.timing;\n \n // Calculate key timings\n const navigationStart = timing.navigationStart;\n const domContentLoaded = timing.domContentLoadedEventEnd - navigationStart;\n const domComplete = timing.domComplete - navigationStart;\n const loadComplete = timing.loadEventEnd - navigationStart;\n const dnsLookup = timing.domainLookupEnd - timing.domainLookupStart;\n const tcpConnection = timing.connectEnd - timing.connectStart;\n const serverResponse = timing.responseEnd - timing.requestStart;\n const domProcessing = timing.domComplete - timing.domLoading;\n\n // Check for impossibly fast load times\n if (domContentLoaded > 0 && domContentLoaded < 10) {\n anomalies.push('instant-dom-content-loaded');\n confidence = Math.max(confidence, 0.7);\n }\n\n // Check for zero DNS lookup (could indicate local file or caching, but suspicious in combination)\n if (dnsLookup === 0 && tcpConnection === 0 && serverResponse < 5) {\n anomalies.push('zero-network-timing');\n confidence = Math.max(confidence, 0.4);\n }\n\n // Check for negative timings (timestamp manipulation)\n if (domContentLoaded < 0 || domComplete < 0 || loadComplete < 0) {\n anomalies.push('negative-timing');\n confidence = Math.max(confidence, 0.8);\n }\n\n // Check for unrealistic timing order\n if (timing.domContentLoadedEventEnd > 0 && timing.loadEventEnd > 0) {\n if (timing.domContentLoadedEventEnd > timing.loadEventEnd) {\n anomalies.push('timing-order-violation');\n confidence = Math.max(confidence, 0.7);\n }\n }\n\n // Check for very long processing times (could indicate headless waiting)\n if (domProcessing > 30000) { // 30 seconds\n anomalies.push('excessive-dom-processing');\n confidence = Math.max(confidence, 0.3);\n }\n\n // Check for script injection timing pattern\n // Bots often inject scripts immediately after load\n const scriptsLoadedTime = timing.domContentLoadedEventStart - timing.responseEnd;\n if (scriptsLoadedTime > 0 && scriptsLoadedTime < 5) {\n anomalies.push('instant-script-execution');\n confidence = Math.max(confidence, 0.4);\n }\n\n // Check for performance.now() manipulation\n const perfNow1 = performance.now();\n const perfNow2 = performance.now();\n \n // If two consecutive calls return the same value (shouldn't happen)\n if (perfNow1 === perfNow2 && perfNow1 > 0) {\n anomalies.push('frozen-performance-now');\n confidence = Math.max(confidence, 0.6);\n }\n\n // Check for Date.now() vs performance.now() consistency\n const dateNow1 = Date.now();\n const perfNow3 = performance.now();\n const dateNow2 = Date.now();\n \n // If they're wildly inconsistent\n if (Math.abs((dateNow2 - dateNow1) - (performance.now() - perfNow3)) > 100) {\n anomalies.push('timing-inconsistency');\n confidence = Math.max(confidence, 0.5);\n }\n\n const triggered = anomalies.length > 0;\n\n return this.createResult(triggered, {\n anomalies,\n timings: {\n domContentLoaded,\n domComplete,\n loadComplete,\n dnsLookup,\n tcpConnection,\n serverResponse,\n domProcessing,\n },\n }, confidence);\n }\n\n /**\n * Analyze Navigation Timing Level 2 API data.\n * @param {PerformanceNavigationTiming} entry - Navigation timing entry\n * @returns {SignalResult}\n */\n _analyzeNavigationTiming(entry) {\n const anomalies = [];\n let confidence = 0;\n\n const domContentLoaded = entry.domContentLoadedEventEnd;\n const loadComplete = entry.loadEventEnd;\n const dnsLookup = entry.domainLookupEnd - entry.domainLookupStart;\n const serverResponse = entry.responseEnd - entry.requestStart;\n\n // Check for impossibly fast load\n if (domContentLoaded > 0 && domContentLoaded < 10) {\n anomalies.push('instant-dom-content-loaded');\n confidence = Math.max(confidence, 0.7);\n }\n\n // Check for zero timings\n if (dnsLookup === 0 && serverResponse === 0) {\n anomalies.push('zero-network-timing');\n confidence = Math.max(confidence, 0.4);\n }\n\n const triggered = anomalies.length > 0;\n\n return this.createResult(triggered, {\n anomalies,\n timings: {\n domContentLoaded,\n loadComplete,\n dnsLookup,\n serverResponse,\n },\n }, confidence);\n }\n}\n\nexport { PageLoadSignal };\n", "/**\n * @fileoverview Analyzes DOM content loaded event timing.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Analyzes timing around DOMContentLoaded event.\n * Bots may have unusual patterns in when/how DOM is processed.\n */\nclass DOMContentTimingSignal extends Signal {\n static id = 'dom-content-timing';\n static category = 'timing';\n static weight = 0.4;\n static description = 'Analyzes DOM content loaded timing patterns';\n\n constructor(options = {}) {\n super(options);\n this._domContentLoadedTime = null;\n this._documentReadyState = document.readyState;\n this._captureTime = performance.now();\n \n // Capture DOMContentLoaded time if not already loaded\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => {\n this._domContentLoadedTime = performance.now();\n });\n }\n }\n\n async detect() {\n const anomalies = [];\n let confidence = 0;\n\n // Get timing information\n const now = performance.now();\n const readyState = document.readyState;\n \n // Check resource timing\n let resourceCount = 0;\n let totalResourceTime = 0;\n let externalScriptCount = 0;\n\n if (performance.getEntriesByType) {\n const resources = performance.getEntriesByType('resource');\n resourceCount = resources.length;\n\n for (const resource of resources) {\n totalResourceTime += resource.duration;\n if (resource.initiatorType === 'script' && \n resource.name.startsWith('http')) {\n externalScriptCount++;\n }\n }\n }\n\n // Check for very few resources (headless often loads minimal)\n if (resourceCount === 0 && readyState === 'complete') {\n anomalies.push('no-resources-loaded');\n confidence = Math.max(confidence, 0.4);\n }\n\n // Check for suspiciously fast DOM ready without resources\n if (this._domContentLoadedTime && this._domContentLoadedTime < 50 && resourceCount === 0) {\n anomalies.push('instant-ready-no-resources');\n confidence = Math.max(confidence, 0.6);\n }\n\n // Check document.hidden state at load\n // Bots often run in hidden/background state\n if (document.hidden && this._documentReadyState === 'loading') {\n anomalies.push('hidden-at-load');\n confidence = Math.max(confidence, 0.3);\n }\n\n // Check for visibility API\n if (typeof document.visibilityState === 'undefined') {\n anomalies.push('no-visibility-api');\n confidence = Math.max(confidence, 0.4);\n }\n\n // Check DOM manipulation timing\n try {\n const startMutation = performance.now();\n const testDiv = document.createElement('div');\n testDiv.id = '__bot_detection_test__';\n document.body.appendChild(testDiv);\n const afterAppend = performance.now();\n document.body.removeChild(testDiv);\n const afterRemove = performance.now();\n\n const appendTime = afterAppend - startMutation;\n const removeTime = afterRemove - afterAppend;\n\n // Instant DOM operations (< 0.01ms) may indicate mocked DOM\n if (appendTime === 0 && removeTime === 0) {\n anomalies.push('instant-dom-operations');\n confidence = Math.max(confidence, 0.5);\n }\n } catch (e) {\n // If body doesn't exist yet, that's unusual at detection time\n if (!document.body) {\n anomalies.push('no-document-body');\n confidence = Math.max(confidence, 0.4);\n }\n }\n\n // Check for MutationObserver availability (should exist in modern browsers)\n if (typeof MutationObserver === 'undefined') {\n anomalies.push('no-mutation-observer');\n confidence = Math.max(confidence, 0.5);\n }\n\n // Check for requestAnimationFrame availability\n if (typeof requestAnimationFrame === 'undefined') {\n anomalies.push('no-request-animation-frame');\n confidence = Math.max(confidence, 0.5);\n }\n\n // Check timing of first paint if available\n if (performance.getEntriesByType) {\n const paintEntries = performance.getEntriesByType('paint');\n const firstPaint = paintEntries.find(e => e.name === 'first-paint');\n \n if (!firstPaint && readyState === 'complete' && now > 1000) {\n anomalies.push('no-first-paint');\n confidence = Math.max(confidence, 0.4);\n }\n\n // Check for first contentful paint\n const fcp = paintEntries.find(e => e.name === 'first-contentful-paint');\n if (!fcp && readyState === 'complete' && now > 1000) {\n anomalies.push('no-first-contentful-paint');\n confidence = Math.max(confidence, 0.4);\n }\n }\n\n // Check intersection observer\n if (typeof IntersectionObserver === 'undefined') {\n anomalies.push('no-intersection-observer');\n confidence = Math.max(confidence, 0.4);\n }\n\n const triggered = anomalies.length > 0;\n\n return this.createResult(triggered, {\n anomalies,\n metrics: {\n readyState,\n resourceCount,\n externalScriptCount,\n domContentLoadedTime: this._domContentLoadedTime,\n documentHidden: document.hidden,\n },\n }, confidence);\n }\n}\n\nexport { DOMContentTimingSignal };\n", "/**\n * @fileoverview Detects Puppeteer-specific artifacts.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Detects artifacts left by Puppeteer automation.\n * Puppeteer leaves various fingerprints in the browser context.\n */\nclass PuppeteerSignal extends Signal {\n static id = 'puppeteer';\n static category = 'automation';\n static weight = 1.0;\n static description = 'Detects Puppeteer automation artifacts';\n\n async detect() {\n const indicators = [];\n let confidence = 0;\n\n // Check for Puppeteer evaluation script marker\n if (window.__puppeteer_evaluation_script__) {\n indicators.push('puppeteer-evaluation-script');\n confidence = Math.max(confidence, 1.0);\n }\n\n // Check for Puppeteer-injected functions\n const puppeteerGlobals = [\n '__puppeteer_evaluation_script__',\n '__puppeteer',\n 'puppeteer',\n ];\n\n for (const global of puppeteerGlobals) {\n if (global in window) {\n indicators.push(`global-${global}`);\n confidence = Math.max(confidence, 1.0);\n }\n }\n\n // Check for HeadlessChrome in user agent (common with Puppeteer)\n const ua = navigator.userAgent || '';\n if (ua.includes('HeadlessChrome')) {\n indicators.push('headless-chrome-ua');\n confidence = Math.max(confidence, 0.9);\n }\n\n // Check for Puppeteer's typical Chrome DevTools Protocol artifacts\n if (window.cdc_adoQpoasnfa76pfcZLmcfl_Array ||\n window.cdc_adoQpoasnfa76pfcZLmcfl_Promise ||\n window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol) {\n indicators.push('cdp-artifacts');\n confidence = Math.max(confidence, 1.0);\n }\n\n // Check for DevTools protocol detection\n try {\n // Puppeteer often leaves eval traces\n const evalTest = window.eval.toString();\n if (evalTest.includes('puppeteer')) {\n indicators.push('eval-puppeteer');\n confidence = Math.max(confidence, 0.9);\n }\n } catch (e) {\n // Ignore errors\n }\n\n // Check for typical Puppeteer page.evaluate patterns in stack traces\n try {\n throw new Error('stack trace test');\n } catch (e) {\n const stack = e.stack || '';\n if (stack.includes('puppeteer') || stack.includes('pptr')) {\n indicators.push('stack-trace-puppeteer');\n confidence = Math.max(confidence, 0.8);\n }\n }\n\n // Check for Puppeteer's default viewport (800x600)\n if (window.innerWidth === 800 && window.innerHeight === 600) {\n // Only weak indicator - could be coincidence\n indicators.push('default-viewport');\n confidence = Math.max(confidence, 0.3);\n }\n\n // Check for navigator.webdriver (Puppeteer sets this)\n if (navigator.webdriver === true) {\n indicators.push('webdriver-flag');\n confidence = Math.max(confidence, 0.9);\n }\n\n // Check for binding injection pattern\n // Puppeteer's exposeFunction creates window bindings\n const suspiciousBindings = Object.keys(window).filter(key => {\n return key.startsWith('__') && typeof window[key] === 'function';\n });\n\n if (suspiciousBindings.length > 3) {\n indicators.push('suspicious-bindings');\n confidence = Math.max(confidence, 0.5);\n }\n\n // Check Chrome object anomalies (Puppeteer headless)\n if (typeof window.chrome !== 'undefined') {\n if (!window.chrome.runtime || !window.chrome.runtime.id) {\n indicators.push('incomplete-chrome-object');\n confidence = Math.max(confidence, 0.4);\n }\n }\n\n const triggered = indicators.length > 0;\n\n return this.createResult(triggered, { indicators }, confidence);\n }\n}\n\nexport { PuppeteerSignal };\n", "/**\n * @fileoverview Detects Playwright-specific artifacts.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Detects artifacts left by Playwright automation.\n * Playwright injects specific objects and leaves traces.\n */\nclass PlaywrightSignal extends Signal {\n static id = 'playwright';\n static category = 'automation';\n static weight = 1.0;\n static description = 'Detects Playwright automation artifacts';\n\n async detect() {\n const indicators = [];\n let confidence = 0;\n\n // Check for Playwright namespace\n if (window.__playwright) {\n indicators.push('playwright-namespace');\n confidence = Math.max(confidence, 1.0);\n }\n\n // Check for Playwright-injected objects\n const playwrightGlobals = [\n '__playwright',\n '__pw_manual',\n '__pwInitScripts',\n 'playwright',\n ];\n\n for (const global of playwrightGlobals) {\n if (global in window) {\n indicators.push(`global-${global}`);\n confidence = Math.max(confidence, 1.0);\n }\n }\n\n // Check for Playwright's binding pattern\n if (window.__playwright__binding__) {\n indicators.push('playwright-binding');\n confidence = Math.max(confidence, 1.0);\n }\n\n // Check for Playwright-specific user agent markers\n const ua = navigator.userAgent || '';\n if (ua.includes('Playwright') || ua.includes('HeadlessChrome')) {\n indicators.push('playwright-ua-marker');\n confidence = Math.max(confidence, ua.includes('Playwright') ? 1.0 : 0.7);\n }\n\n // Check for navigator.webdriver (Playwright sets this in headless)\n if (navigator.webdriver === true) {\n indicators.push('webdriver-flag');\n confidence = Math.max(confidence, 0.8);\n }\n\n // Check for Playwright's evaluate scope pattern\n try {\n // Playwright injects __pwBinding__ functions\n const windowKeys = Object.keys(window);\n const pwBindings = windowKeys.filter(k => k.startsWith('__pw'));\n \n if (pwBindings.length > 0) {\n indicators.push('pw-bindings');\n confidence = Math.max(confidence, 1.0);\n }\n } catch (e) {\n // Ignore errors\n }\n\n // Check for Playwright's typical initialization patterns\n if (typeof window.__pw_date_intercepted !== 'undefined') {\n indicators.push('date-interception');\n confidence = Math.max(confidence, 0.9);\n }\n\n // Check for Playwright's geolocation mock\n if (window.__pw_geolocation__) {\n indicators.push('geolocation-mock');\n confidence = Math.max(confidence, 0.9);\n }\n\n // Check for Playwright's permission override\n if (window.__pw_permissions__) {\n indicators.push('permissions-override');\n confidence = Math.max(confidence, 0.9);\n }\n\n // Check CDP session artifacts\n if (window.__cdpSession__) {\n indicators.push('cdp-session');\n confidence = Math.max(confidence, 0.8);\n }\n\n // Check for error stack traces containing Playwright\n try {\n throw new Error('stack trace test');\n } catch (e) {\n const stack = e.stack || '';\n if (stack.includes('playwright') || stack.includes('__pw')) {\n indicators.push('stack-trace-playwright');\n confidence = Math.max(confidence, 0.8);\n }\n }\n\n // Check for Playwright's locale/timezone mocking\n try {\n const date = new Date();\n const localeString = date.toLocaleString();\n // Playwright often mocks timezone\n if (window.__pwTimezone__) {\n indicators.push('timezone-mock');\n confidence = Math.max(confidence, 0.8);\n }\n } catch (e) {\n // Ignore errors\n }\n\n const triggered = indicators.length > 0;\n\n return this.createResult(triggered, { indicators }, confidence);\n }\n}\n\nexport { PlaywrightSignal };\n", "/**\n * @fileoverview Detects Selenium WebDriver artifacts.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Detects artifacts left by Selenium WebDriver.\n * Selenium leaves various fingerprints in the browser context.\n */\nclass SeleniumSignal extends Signal {\n static id = 'selenium';\n static category = 'automation';\n static weight = 1.0;\n static description = 'Detects Selenium WebDriver artifacts';\n\n async detect() {\n const indicators = [];\n let confidence = 0;\n\n // Check for navigator.webdriver (standard WebDriver flag)\n if (navigator.webdriver === true) {\n indicators.push('webdriver-flag');\n confidence = Math.max(confidence, 1.0);\n }\n\n // Check for Selenium-specific globals\n const seleniumGlobals = [\n '_selenium',\n 'callSelenium',\n '_Selenium_IDE_Recorder',\n '__selenium_evaluate',\n '__selenium_unwrap',\n '__webdriver_evaluate',\n '__webdriver_unwrap',\n '__webdriver_script_function',\n '__webdriver_script_func',\n '__fxdriver_evaluate',\n '__fxdriver_unwrap',\n 'webdriver',\n ];\n\n for (const global of seleniumGlobals) {\n if (global in window) {\n indicators.push(`global-${global}`);\n confidence = Math.max(confidence, 1.0);\n }\n }\n\n // Check for Selenium document properties\n const seleniumDocProps = [\n '__webdriver_script_fn',\n '__driver_evaluate',\n '__webdriver_evaluate',\n '__selenium_evaluate',\n '__fxdriver_evaluate',\n '__driver_unwrap',\n '__webdriver_unwrap',\n '__selenium_unwrap',\n '__fxdriver_unwrap',\n ];\n\n for (const prop of seleniumDocProps) {\n if (prop in document) {\n indicators.push(`document-${prop}`);\n confidence = Math.max(confidence, 1.0);\n }\n }\n\n // Check for ChromeDriver artifacts ($cdc variables)\n const windowKeys = Object.keys(window);\n \n // ChromeDriver injects variables starting with $cdc_ or $wdc_\n const cdcVars = windowKeys.filter(key => \n key.startsWith('$cdc_') || \n key.startsWith('$wdc_') ||\n key.startsWith('$chrome_asyncScriptInfo')\n );\n\n if (cdcVars.length > 0) {\n indicators.push('chromedriver-variables');\n confidence = Math.max(confidence, 1.0);\n }\n\n // Check for GeckoDriver (Firefox) artifacts\n if (window.webdriverCallback || document.documentElement.getAttribute('webdriver')) {\n indicators.push('geckodriver-artifacts');\n confidence = Math.max(confidence, 1.0);\n }\n\n // Check for webdriver in document element attributes\n try {\n const docElement = document.documentElement;\n if (docElement.hasAttribute('webdriver') || \n docElement.getAttribute('selenium') ||\n docElement.getAttribute('driver')) {\n indicators.push('document-webdriver-attr');\n confidence = Math.max(confidence, 1.0);\n }\n } catch (e) {\n // Ignore errors\n }\n\n // Check for Selenium IDE artifacts\n if (window.selenium || window.sideex) {\n indicators.push('selenium-ide');\n confidence = Math.max(confidence, 1.0);\n }\n\n // Check for navigator.webdriver property descriptor anomalies\n try {\n const descriptor = Object.getOwnPropertyDescriptor(Navigator.prototype, 'webdriver');\n if (descriptor) {\n // Check if the getter has been modified\n if (descriptor.get) {\n const getterStr = descriptor.get.toString();\n if (!getterStr.includes('[native code]')) {\n indicators.push('webdriver-getter-modified');\n confidence = Math.max(confidence, 0.7);\n }\n }\n }\n } catch (e) {\n // Ignore errors\n }\n\n // Check for driver command executor\n if (window.domAutomation || window.domAutomationController) {\n indicators.push('dom-automation');\n confidence = Math.max(confidence, 1.0);\n }\n\n // Check for callPhantom alternative used by some Selenium setups\n if (window.awesomium) {\n indicators.push('awesomium');\n confidence = Math.max(confidence, 0.9);\n }\n\n // Check for external interface (used by some automation tools)\n if (window.external && window.external.toString().includes('Selenium')) {\n indicators.push('external-selenium');\n confidence = Math.max(confidence, 1.0);\n }\n\n const triggered = indicators.length > 0;\n\n return this.createResult(triggered, { indicators }, confidence);\n }\n}\n\nexport { SeleniumSignal };\n", "/**\n * @fileoverview Detects PhantomJS-specific artifacts.\n */\n\nimport { Signal } from '../../core/Signal.js';\n\n/**\n * Detects artifacts left by PhantomJS.\n * PhantomJS is an older headless browser that leaves specific traces.\n */\nclass PhantomJSSignal extends Signal {\n static id = 'phantomjs';\n static category = 'automation';\n static weight = 1.0;\n static description = 'Detects PhantomJS automation artifacts';\n\n async detect() {\n const indicators = [];\n let confidence = 0;\n\n // Check for PhantomJS globals\n if (window.callPhantom) {\n indicators.push('callPhantom');\n confidence = Math.max(confidence, 1.0);\n }\n\n if (window._phantom) {\n indicators.push('_phantom');\n confidence = Math.max(confidence, 1.0);\n }\n\n if (window.phantom) {\n indicators.push('phantom');\n confidence = Math.max(confidence, 1.0);\n }\n\n // Check for PhantomJS in user agent\n const ua = navigator.userAgent || '';\n if (ua.includes('PhantomJS')) {\n indicators.push('phantomjs-ua');\n confidence = Math.max(confidence, 1.0);\n }\n\n // Check for PhantomJS specific properties\n if (window.__phantomas) {\n indicators.push('phantomas');\n confidence = Math.max(confidence, 1.0);\n }\n\n // Check for CasperJS (built on PhantomJS)\n if (window.__casper) {\n indicators.push('casperjs');\n confidence = Math.max(confidence, 1.0);\n }\n\n if (window.casper) {\n indicators.push('casper-global');\n confidence = Math.max(confidence, 1.0);\n }\n\n // Check for SlimerJS (PhantomJS alternative)\n if (window.slimer) {\n indicators.push('slimerjs');\n confidence = Math.max(confidence, 1.0);\n }\n\n // Check for NightmareJS (Electron-based, similar patterns)\n if (window.__nightmare) {\n indicators.push('nightmare');\n confidence = Math.max(confidence, 1.0);\n }\n\n if (window.nightmare) {\n indicators.push('nightmare-global');\n confidence = Math.max(confidence, 1.0);\n }\n\n // Check for function sources containing PhantomJS\n try {\n const funcString = Function.prototype.toString.call(Function);\n if (funcString.includes('phantom') || funcString.includes('Phantom')) {\n indicators.push('function-prototype-phantom');\n confidence = Math.max(confidence, 0.8);\n }\n } catch (e) {\n // Ignore errors\n }\n\n // Check for PhantomJS-specific behaviors\n // PhantomJS has a specific way of handling errors\n try {\n throw new Error('test');\n } catch (e) {\n const stack = e.stack || '';\n if (stack.includes('phantom')) {\n indicators.push('stack-trace-phantom');\n confidence = Math.max(confidence, 0.9);\n }\n }\n\n // Check for PhantomJS-specific plugin handling\n if (navigator.plugins && navigator.plugins.length === 0) {\n // Combined with other PhantomJS indicators\n if (indicators.length > 0) {\n indicators.push('no-plugins-phantom');\n confidence = Math.max(confidence, 0.5);\n }\n }\n\n // Check for specific PhantomJS window properties\n const phantomProps = [\n '__PHANTOM__',\n 'PHANTOM',\n 'Buffer', // PhantomJS exposes Node.js Buffer\n 'process', // May expose Node.js process\n ];\n\n for (const prop of phantomProps) {\n if (prop in window && prop !== 'Buffer' && prop !== 'process') {\n indicators.push(`phantom-prop-${prop.toLowerCase()}`);\n confidence = Math.max(confidence, 0.9);\n }\n }\n\n // Check for QtWebKit (PhantomJS engine)\n if (ua.includes('QtWebKit')) {\n indicators.push('qtwebkit');\n confidence = Math.max(confidence, 0.7);\n }\n\n const triggered = indicators.length > 0;\n\n return this.createResult(triggered, { indicators }, confidence);\n }\n}\n\nexport { PhantomJSSignal };\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1 @@
1
+ var BotDetectorLib=(()=>{var $=Object.defineProperty;var nt=Object.getOwnPropertyDescriptor;var st=Object.getOwnPropertyNames;var ot=Object.prototype.hasOwnProperty;var at=(g,e,t)=>e in g?$(g,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):g[e]=t;var rt=(g,e)=>{for(var t in e)$(g,t,{get:e[t],enumerable:!0})},ct=(g,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of st(e))!ot.call(g,i)&&i!==t&&$(g,i,{get:()=>e[i],enumerable:!(n=nt(e,i))||n.enumerable});return g};var ht=g=>ct($({},"__esModule",{value:!0}),g);var o=(g,e,t)=>at(g,typeof e!="symbol"?e+"":e,t);var dt={};rt(dt,{AudioContextSignal:()=>I,BotDetector:()=>j,CanvasSignal:()=>P,DOMContentTimingSignal:()=>O,HeadlessSignal:()=>C,InteractionTimingSignal:()=>b,KeyboardPatternSignal:()=>M,MouseMovementSignal:()=>y,NavigatorAnomalySignal:()=>R,PageLoadSignal:()=>A,PermissionsSignal:()=>D,PhantomJSSignal:()=>q,PlaywrightSignal:()=>V,PluginsSignal:()=>S,PuppeteerSignal:()=>B,ScoringEngine:()=>U,ScreenSignal:()=>H,ScrollBehaviorSignal:()=>T,SeleniumSignal:()=>K,Signal:()=>m,Signals:()=>tt,Verdict:()=>z,VerdictEngine:()=>N,WebDriverSignal:()=>E,WebGLSignal:()=>L,createDetector:()=>Z,default:()=>ut,defaultInstantSignals:()=>G,defaultInteractionSignals:()=>Q,defaultSignals:()=>lt,detect:()=>J,detectInstant:()=>et});var m=class{constructor(e={}){this.options=e,this._lastResult=null}get id(){return this.constructor.id}get category(){return this.constructor.category}get weight(){var e;return(e=this.options.weight)!=null?e:this.constructor.weight}get description(){return this.constructor.description}get requiresInteraction(){return this.constructor.requiresInteraction}get lastResult(){return this._lastResult}async detect(){throw new Error(`Signal.detect() must be implemented by ${this.constructor.name}`)}async run(){try{return this._lastResult=await this.detect(),this._lastResult}catch(e){return this._lastResult={triggered:!1,value:null,confidence:0,error:e.message},this._lastResult}}reset(){this._lastResult=null}createResult(e,t=null,n=1){return{triggered:!!e,value:t,confidence:Math.max(0,Math.min(1,n))}}};o(m,"id","base-signal"),o(m,"category","uncategorized"),o(m,"weight",.5),o(m,"description","Base signal class"),o(m,"requiresInteraction",!1);var U=class{constructor(e={}){this.weightOverrides=e.weightOverrides||{},this.maxScore=e.maxScore||100,this._results=new Map}getWeight(e,t){var n;return(n=this.weightOverrides[e])!=null?n:t}addResult(e,t,n){let i=this.getWeight(e,n);this._results.set(e,{...t,weight:i,contribution:t.triggered?i*t.confidence:0})}calculate(){if(this._results.size===0)return 0;let e=0,t=0;for(let[,i]of this._results)e+=i.weight,t+=i.contribution;if(e===0)return 0;let n=t/e*this.maxScore;return Math.round(n*100)/100}getBreakdown(){let e=[];for(let[t,n]of this._results)e.push({signalId:t,triggered:n.triggered,confidence:n.confidence,weight:n.weight,contribution:n.contribution,percentOfScore:this.calculate()>0?(n.contribution/this.calculate()*100).toFixed(1):"0.0"});return e.sort((t,n)=>n.contribution-t.contribution)}getTriggeredSignals(){let e=[];for(let[t,n]of this._results)n.triggered&&e.push(t);return e}getTriggeredCount(){let e=0;for(let[,t]of this._results)t.triggered&&e++;return e}reset(){this._results.clear()}};var z={HUMAN:"human",SUSPICIOUS:"suspicious",BOT:"bot"},F=class F{constructor(e={}){var t,n;this.humanThreshold=(t=e.humanThreshold)!=null?t:F.DEFAULT_THRESHOLDS.human,this.suspiciousThreshold=(n=e.suspiciousThreshold)!=null?n:F.DEFAULT_THRESHOLDS.suspicious,this.instantBotSignals=new Set(e.instantBotSignals||[])}getVerdict(e,t=[]){for(let c of t)if(this.instantBotSignals.has(c))return{verdict:z.BOT,score:e,confidence:"high",reason:`Instant bot signal triggered: ${c}`,triggeredCount:t.length};let n,i,s;return e<this.humanThreshold?(n=z.HUMAN,i=e<10?"high":"medium",s="Low bot score"):e<this.suspiciousThreshold?(n=z.SUSPICIOUS,i="medium",s="Moderate bot indicators detected"):(n=z.BOT,i=e>=75?"high":"medium",s="High accumulation of bot indicators"),{verdict:n,score:e,confidence:i,reason:s,triggeredCount:t.length}}isInstantBotSignal(e){return this.instantBotSignals.has(e)}addInstantBotSignal(e){this.instantBotSignals.add(e)}setThresholds(e){e.human!==void 0&&(this.humanThreshold=e.human),e.suspicious!==void 0&&(this.suspiciousThreshold=e.suspicious)}};o(F,"DEFAULT_THRESHOLDS",{human:20,suspicious:50});var N=F;var j=class g{constructor(e={}){if(this.options=e,this._signals=new Map,this._scoringEngine=new U({weightOverrides:e.weightOverrides}),this._verdictEngine=new N({humanThreshold:e.humanThreshold,suspiciousThreshold:e.suspiciousThreshold,instantBotSignals:e.instantBotSignals}),this._lastDetection=null,this._detectionTimeout=e.detectionTimeout||5e3,this._isRunning=!1,e.signals)for(let t of e.signals)this.registerSignal(t)}registerSignal(e){if(!(e instanceof m))throw new Error("Signal must be an instance of Signal class");let t=e.id;if(this._signals.has(t))throw new Error(`Signal with ID "${t}" is already registered`);return this._signals.set(t,e),this}registerSignals(e){for(let t of e)this.registerSignal(t);return this}unregisterSignal(e){return this._signals.delete(e)}getSignal(e){return this._signals.get(e)}getSignals(){return Array.from(this._signals.values())}getSignalsByCategory(e){return this.getSignals().filter(t=>t.category===e)}async detect(e={}){if(this._isRunning)throw new Error("Detection is already running");this._isRunning=!0,this._scoringEngine.reset();let t=performance.now(),n=new Map;try{let i=this.getSignals().filter(u=>!(e.skipInteractionSignals&&u.requiresInteraction)),s=i.map(async u=>{let l=await Promise.race([u.run(),new Promise(h=>setTimeout(()=>h({triggered:!1,value:null,confidence:0,error:"timeout"}),this._detectionTimeout))]);return{signal:u,result:l}}),c=await Promise.all(s);for(let{signal:u,result:l}of c)n.set(u.id,{...l,category:u.category,weight:u.weight,description:u.description}),this._scoringEngine.addResult(u.id,l,u.weight);let r=this._scoringEngine.calculate(),a=this._scoringEngine.getTriggeredSignals(),p=this._verdictEngine.getVerdict(r,a),d=performance.now()-t;return this._lastDetection={...p,signals:Object.fromEntries(n),breakdown:this._scoringEngine.getBreakdown(),timestamp:Date.now(),detectionTimeMs:Math.round(d),totalSignals:i.length,triggeredSignals:a},this._lastDetection}finally{this._isRunning=!1}}getLastDetection(){return this._lastDetection}getScore(){var e,t;return(t=(e=this._lastDetection)==null?void 0:e.score)!=null?t:0}getTriggeredSignals(){var e,t;return(t=(e=this._lastDetection)==null?void 0:e.triggeredSignals)!=null?t:[]}isRunning(){return this._isRunning}reset(){this._scoringEngine.reset(),this._lastDetection=null;for(let e of this._signals.values())e.reset()}configure(e){(e.humanThreshold!==void 0||e.suspiciousThreshold!==void 0)&&this._verdictEngine.setThresholds({human:e.humanThreshold,suspicious:e.suspiciousThreshold}),e.detectionTimeout!==void 0&&(this._detectionTimeout=e.detectionTimeout)}static withDefaults(e={}){return new g(e)}};var E=class extends m{async detect(){if(navigator.webdriver===!0)return this.createResult(!0,{webdriver:!0},1);let e=Object.getOwnPropertyDescriptor(navigator,"webdriver");if(e&&(e.get||!e.configurable))return this.createResult(!0,{webdriver:"modified",descriptor:{configurable:e.configurable,enumerable:e.enumerable,hasGetter:!!e.get}},.8);try{let t=Object.getPrototypeOf(navigator),n=Object.getOwnPropertyDescriptor(t,"webdriver");if(n&&n.get&&n.get.call(navigator)===!0)return this.createResult(!0,{webdriver:!0,source:"prototype"},1)}catch{}return this.createResult(!1)}};o(E,"id","webdriver"),o(E,"category","environment"),o(E,"weight",1),o(E,"description","Detects navigator.webdriver automation flag");var C=class extends m{async detect(){let e=[],t=0,n=navigator.userAgent||"";n.includes("HeadlessChrome")&&(e.push("headless-ua"),t=Math.max(t,1)),n.includes("Chrome")&&!n.includes("Chromium")&&(typeof window.chrome>"u"?(e.push("missing-chrome-object"),t=Math.max(t,.6)):window.chrome.runtime||(e.push("missing-chrome-runtime"),t=Math.max(t,.4))),navigator.plugins&&navigator.plugins.length===0&&(e.push("no-plugins"),t=Math.max(t,.5)),(!navigator.languages||navigator.languages.length===0)&&(e.push("no-languages"),t=Math.max(t,.6)),window.outerWidth===0&&window.outerHeight===0&&(e.push("zero-outer-dimensions"),t=Math.max(t,.7)),typeof navigator.connection>"u"&&n.includes("Chrome")&&(e.push("missing-connection-api"),t=Math.max(t,.3));try{typeof Notification<"u"&&Notification.permission==="denied"&&window.outerWidth===0&&(e.push("notification-headless-pattern"),t=Math.max(t,.5))}catch{}(window.callPhantom||window._phantom)&&(e.push("phantomjs"),t=Math.max(t,1)),window.__nightmare&&(e.push("nightmare"),t=Math.max(t,1));let i=e.length>0;return e.length>=3&&(t=Math.min(1,t+.2)),this.createResult(i,{indicators:e},t)}};o(C,"id","headless"),o(C,"category","environment"),o(C,"weight",.8),o(C,"description","Detects headless browser indicators");var R=class extends m{async detect(){let e=[],t=0,n=0,i=navigator.userAgent||"",s=navigator.platform||"";n++,s.includes("Win")&&!i.includes("Windows")?(e.push("platform-ua-mismatch-windows"),t+=1):s.includes("Mac")&&!i.includes("Mac")?(e.push("platform-ua-mismatch-mac"),t+=1):s.includes("Linux")&&!i.includes("Linux")&&!i.includes("Android")&&(e.push("platform-ua-mismatch-linux"),t+=1),n++,(!s||s===""||s==="undefined")&&(e.push("empty-platform"),t+=1),n++,navigator.language&&navigator.languages&&(navigator.languages.includes(navigator.language)||(e.push("language-mismatch"),t+=.5)),n++,i.includes("Chrome")&&navigator.vendor!=="Google Inc."?(e.push("vendor-mismatch-chrome"),t+=.5):i.includes("Firefox")&&navigator.vendor!==""?(e.push("vendor-mismatch-firefox"),t+=.5):i.includes("Safari")&&!i.includes("Chrome")&&navigator.vendor!=="Apple Computer, Inc."&&(e.push("vendor-mismatch-safari"),t+=.5),n++,typeof navigator.hardwareConcurrency<"u"&&(navigator.hardwareConcurrency===0||navigator.hardwareConcurrency>128)&&(e.push("suspicious-hardware-concurrency"),t+=.5),n++,typeof navigator.deviceMemory<"u"&&(navigator.deviceMemory===0||navigator.deviceMemory>512)&&(e.push("suspicious-device-memory"),t+=.5),n++;let c=/Android|iPhone|iPad|iPod|Mobile/i.test(i),r=navigator.maxTouchPoints>0;!c&&navigator.maxTouchPoints>5&&(e.push("desktop-high-touch-points"),t+=.3),n++;try{let d=Object.getOwnPropertyDescriptor(Navigator.prototype,"userAgent");d&&d.get&&d.get.toString().includes("native code")===!1&&(e.push("spoofed-user-agent"),t+=1)}catch{}let a=e.length>0,p=Math.min(1,t/Math.max(1,n));return this.createResult(a,{anomalies:e},p)}};o(R,"id","navigator-anomaly"),o(R,"category","environment"),o(R,"weight",.7),o(R,"description","Detects navigator property inconsistencies");var D=class extends m{async detect(){let e=[];if(!navigator.permissions)return this.createResult(!1,{supported:!1},0);try{let i=await navigator.permissions.query({name:"notifications"});if(typeof Notification<"u"){let s=Notification.permission;(s==="granted"&&i.state!=="granted"||s==="denied"&&i.state!=="denied"||s==="default"&&i.state!=="prompt")&&e.push("notification-permission-mismatch")}try{(await navigator.permissions.query({name:"geolocation"})).state==="denied"&&window.outerWidth===0&&e.push("geo-denied-headless")}catch{}try{await navigator.permissions.query({name:"camera"})}catch(s){s.name==="TypeError"&&e.push("camera-permission-error")}}catch(i){i.name!=="TypeError"&&e.push("permissions-query-error")}let t=e.length>0,n=Math.min(1,e.length*.4);return this.createResult(t,{anomalies:e},n)}};o(D,"id","permissions"),o(D,"category","environment"),o(D,"weight",.5),o(D,"description","Detects Permissions API anomalies");var y=class extends m{constructor(e={}){super(e),this._movements=[],this._isTracking=!1,this._trackingDuration=e.trackingDuration||3e3,this._minMovements=e.minMovements||5,this._boundHandler=null}startTracking(){this._isTracking||(this._movements=[],this._isTracking=!0,this._boundHandler=e=>{this._movements.push({x:e.clientX,y:e.clientY,t:performance.now()})},document.addEventListener("mousemove",this._boundHandler,{passive:!0}))}stopTracking(){this._isTracking&&(this._isTracking=!1,this._boundHandler&&(document.removeEventListener("mousemove",this._boundHandler),this._boundHandler=null))}async detect(){let e=[],t=0;this._movements.length===0&&(this.startTracking(),await new Promise(c=>setTimeout(c,this._trackingDuration)),this.stopTracking());let n=this._movements;if(n.length<this._minMovements)return e.push("no-mouse-movement"),t=Math.max(t,.6),this.createResult(!0,{anomalies:e,movements:n.length},t);let i=this._analyzeMovements(n);i.teleportCount>0&&(e.push("mouse-teleportation"),t=Math.max(t,.7)),i.linearPathRatio>.9&&(e.push("linear-path"),t=Math.max(t,.8)),i.velocityVariance<.01&&n.length>10&&(e.push("constant-velocity"),t=Math.max(t,.7)),i.accelerationChanges===0&&n.length>10&&(e.push("no-acceleration-variance"),t=Math.max(t,.6)),i.timingVariance<1&&n.length>10&&(e.push("robotic-timing"),t=Math.max(t,.8));let s=e.length>0;return this.createResult(s,{anomalies:e,movementCount:n.length,analysis:i},t)}_analyzeMovements(e){if(e.length<3)return{teleportCount:0,linearPathRatio:0,velocityVariance:0,accelerationChanges:0,timingVariance:0};let t=0,n=[],i=[],s=[];for(let l=1;l<e.length;l++){let h=e[l-1],f=e[l],x=f.x-h.x,_=f.y-h.y,w=f.t-h.t;if(w===0)continue;let k=Math.sqrt(x*x+_*_),v=k/w;n.push(v),i.push(Math.atan2(_,x)),s.push(w),k>300&&w<10&&t++}let c=n.reduce((l,h)=>l+h,0)/n.length,r=n.reduce((l,h)=>l+Math.pow(h-c,2),0)/n.length,a=0;if(i.length>1){let l=0;for(let h=1;h<i.length;h++)Math.abs(i[h]-i[h-1])<.1&&l++;a=l/(i.length-1)}let p=s.reduce((l,h)=>l+h,0)/s.length,d=s.reduce((l,h)=>l+Math.pow(h-p,2),0)/s.length,u=0;for(let l=1;l<n.length;l++)(n[l]-n[l-1])*(n[l-1]-(n[l-2]||0))<0&&u++;return{teleportCount:t,linearPathRatio:a,velocityVariance:r,accelerationChanges:u,timingVariance:d}}reset(){super.reset(),this.stopTracking(),this._movements=[]}};o(y,"id","mouse-movement"),o(y,"category","behavior"),o(y,"weight",.9),o(y,"description","Detects non-human mouse movement patterns"),o(y,"requiresInteraction",!0);var M=class extends m{constructor(e={}){super(e),this._keystrokes=[],this._isTracking=!1,this._trackingDuration=e.trackingDuration||5e3,this._minKeystrokes=e.minKeystrokes||10,this._boundKeydownHandler=null,this._boundKeyupHandler=null}startTracking(){this._isTracking||(this._keystrokes=[],this._isTracking=!0,this._boundKeydownHandler=e=>{this._keystrokes.push({type:"down",key:e.key,code:e.code,t:performance.now()})},this._boundKeyupHandler=e=>{this._keystrokes.push({type:"up",key:e.key,code:e.code,t:performance.now()})},document.addEventListener("keydown",this._boundKeydownHandler,{passive:!0}),document.addEventListener("keyup",this._boundKeyupHandler,{passive:!0}))}stopTracking(){this._isTracking&&(this._isTracking=!1,this._boundKeydownHandler&&(document.removeEventListener("keydown",this._boundKeydownHandler),this._boundKeydownHandler=null),this._boundKeyupHandler&&(document.removeEventListener("keyup",this._boundKeyupHandler),this._boundKeyupHandler=null))}async detect(){let e=[],t=0;this._keystrokes.length===0&&(this.startTracking(),await new Promise(r=>setTimeout(r,this._trackingDuration)),this.stopTracking());let n=this._keystrokes,i=n.filter(r=>r.type==="down");if(i.length<this._minKeystrokes)return this.createResult(!1,{reason:"insufficient-data",keystrokes:i.length},0);let s=this._analyzeKeystrokes(n);s.avgInterKeystrokeTime<50&&i.length>20&&(e.push("inhuman-speed"),t=Math.max(t,.9)),s.timingVariance<5&&i.length>15&&(e.push("robotic-timing"),t=Math.max(t,.8)),s.missingKeyups>i.length*.5&&(e.push("missing-keyups"),t=Math.max(t,.7)),s.holdTimeVariance<2&&s.holdTimes.length>10&&(e.push("constant-hold-time"),t=Math.max(t,.6)),s.sequentialKeys>i.length*.8&&i.length>10&&(e.push("sequential-input"),t=Math.max(t,.5)),s.rhythmScore<.1&&i.length>20&&(e.push("no-rhythm-variation"),t=Math.max(t,.6));let c=e.length>0;return this.createResult(c,{anomalies:e,keystrokeCount:i.length,analysis:s},t)}_analyzeKeystrokes(e){let t=e.filter(h=>h.type==="down"),n=e.filter(h=>h.type==="up");if(t.length<2)return{avgInterKeystrokeTime:1/0,timingVariance:1/0,missingKeyups:0,holdTimeVariance:1/0,holdTimes:[],sequentialKeys:0,rhythmScore:1};let i=[];for(let h=1;h<t.length;h++)i.push(t[h].t-t[h-1].t);let s=i.reduce((h,f)=>h+f,0)/i.length,c=i.reduce((h,f)=>h+Math.pow(f-s,2),0)/i.length,r=[];for(let h of t){let f=n.find(x=>x.key===h.key&&x.t>h.t);f&&r.push(f.t-h.t)}let a=r.length>0?r.reduce((h,f)=>h+f,0)/r.length:0,p=r.length>0?r.reduce((h,f)=>h+Math.pow(f-a,2),0)/r.length:1/0,d=t.length-r.length,u=0;for(let h=1;h<t.length;h++){let f=t[h-1].key.charCodeAt(0),x=t[h].key.charCodeAt(0);Math.abs(x-f)===1&&u++}let l=0;if(i.length>5){let h=[...i].sort((_,w)=>_-w),f=h[Math.floor(h.length/2)];l=i.filter(_=>Math.abs(_-f)>f*.3).length/i.length}return{avgInterKeystrokeTime:s,timingVariance:c,missingKeyups:d,holdTimeVariance:p,holdTimes:r,sequentialKeys:u,rhythmScore:l}}reset(){super.reset(),this.stopTracking(),this._keystrokes=[]}};o(M,"id","keyboard-pattern"),o(M,"category","behavior"),o(M,"weight",.8),o(M,"description","Detects non-human keystroke patterns"),o(M,"requiresInteraction",!0);var b=class extends m{constructor(e={}){super(e),this._pageLoadTime=performance.now(),this._firstInteractionTime=null,this._interactions=[],this._isTracking=!1,this._trackingDuration=e.trackingDuration||5e3,this._boundHandler=null}startTracking(){if(this._isTracking)return;this._interactions=[],this._isTracking=!0;let e=["click","mousedown","touchstart","keydown","scroll"];this._boundHandler=t=>{let n=performance.now();this._firstInteractionTime===null&&(this._firstInteractionTime=n),this._interactions.push({type:t.type,t:n,timeSinceLoad:n-this._pageLoadTime})};for(let t of e)document.addEventListener(t,this._boundHandler,{passive:!0,capture:!0})}stopTracking(){if(!this._isTracking)return;this._isTracking=!1;let e=["click","mousedown","touchstart","keydown","scroll"];if(this._boundHandler){for(let t of e)document.removeEventListener(t,this._boundHandler,{capture:!0});this._boundHandler=null}}async detect(){let e=[],t=0;!this._isTracking&&this._interactions.length===0&&(this.startTracking(),await new Promise(r=>setTimeout(r,this._trackingDuration)),this.stopTracking());let n=this._interactions;if(n.length===0)return this.createResult(!1,{reason:"no-interactions"},0);let i=n[0];if(i.timeSinceLoad<100?(e.push("instant-interaction"),t=Math.max(t,.9)):i.timeSinceLoad<300&&(e.push("very-fast-interaction"),t=Math.max(t,.6)),n.length>3){let r=[];for(let l=1;l<n.length;l++)r.push(n[l].t-n[l-1].t);let a=r.reduce((l,h)=>l+h,0)/r.length;r.reduce((l,h)=>l+Math.pow(h-a,2),0)/r.length<10&&n.length>5&&(e.push("robotic-intervals"),t=Math.max(t,.8));let d=50,u=0;for(let l of r)l<d&&u++;u>r.length*.7&&(e.push("burst-interactions"),t=Math.max(t,.7))}let s=n.map(r=>r.type).join(",");if(n.length>=6){let r=Math.floor(n.length/2),a=n.slice(0,r).map(d=>d.type).join(","),p=n.slice(r,r*2).map(d=>d.type).join(",");a===p&&a.length>0&&(e.push("repeated-sequence"),t=Math.max(t,.6))}let c=e.length>0;return this.createResult(c,{anomalies:e,interactionCount:n.length,timeToFirstInteraction:i.timeSinceLoad,firstInteractionType:i.type},t)}reset(){super.reset(),this.stopTracking(),this._pageLoadTime=performance.now(),this._firstInteractionTime=null,this._interactions=[]}};o(b,"id","interaction-timing"),o(b,"category","behavior"),o(b,"weight",.6),o(b,"description","Detects suspicious interaction timing"),o(b,"requiresInteraction",!0);var T=class extends m{constructor(e={}){super(e),this._scrollEvents=[],this._isTracking=!1,this._trackingDuration=e.trackingDuration||3e3,this._boundHandler=null}startTracking(){this._isTracking||(this._scrollEvents=[],this._isTracking=!0,this._boundHandler=()=>{this._scrollEvents.push({scrollY:window.scrollY,scrollX:window.scrollX,t:performance.now()})},window.addEventListener("scroll",this._boundHandler,{passive:!0}))}stopTracking(){this._isTracking&&(this._isTracking=!1,this._boundHandler&&(window.removeEventListener("scroll",this._boundHandler),this._boundHandler=null))}async detect(){let e=[],t=0;this._scrollEvents.length===0&&(this.startTracking(),await new Promise(c=>setTimeout(c,this._trackingDuration)),this.stopTracking());let n=this._scrollEvents;if(n.length<3)return this.createResult(!1,{reason:"insufficient-scroll-data",scrollEvents:n.length},0);let i=this._analyzeScrollPatterns(n);i.instantJumps>0&&(e.push("instant-scroll-jumps"),t=Math.max(t,.7)),i.velocityVariance<.1&&n.length>10&&(e.push("constant-scroll-velocity"),t=Math.max(t,.6)),i.momentumEvents===0&&n.length>5&&(e.push("no-scroll-momentum"),t=Math.max(t,.5)),i.intervalVariance<5&&n.length>10&&(e.push("robotic-scroll-timing"),t=Math.max(t,.7)),i.scrollDirections===1&&Math.abs(i.totalScrollY)>1e3&&i.velocityVariance<1&&(e.push("one-dimensional-scroll"),t=Math.max(t,.4)),i.exactPositionScrolls>2&&(e.push("exact-position-scrolls"),t=Math.max(t,.6));let s=e.length>0;return this.createResult(s,{anomalies:e,scrollEventCount:n.length,analysis:i},t)}_analyzeScrollPatterns(e){if(e.length<2)return{instantJumps:0,velocityVariance:0,momentumEvents:0,intervalVariance:0,scrollDirections:0,totalScrollY:0,exactPositionScrolls:0};let t=0,n=0,i=[],s=[],c=!1,r=!1,a=0,p=[0,100,200,300,400,500,600,800,1e3];for(let _=1;_<e.length;_++){let w=e[_-1],k=e[_],v=k.scrollY-w.scrollY,W=k.scrollX-w.scrollX,Y=k.t-w.t;if(s.push(Y),Math.abs(v)>0&&(c=!0),Math.abs(W)>0&&(r=!0),Y===0)continue;let X=Math.sqrt(v*v+W*W)/Y;if(i.push(X),Math.abs(v)+Math.abs(W)>200&&Y<20&&t++,_>1&&i.length>1){let it=i[i.length-2];X<it*.9&&X>0&&n++}p.includes(Math.round(k.scrollY))&&a++}let d=i.length>0?i.reduce((_,w)=>_+w,0)/i.length:0,u=i.length>0?i.reduce((_,w)=>_+Math.pow(w-d,2),0)/i.length:0,l=s.reduce((_,w)=>_+w,0)/s.length,h=s.reduce((_,w)=>_+Math.pow(w-l,2),0)/s.length,f=0;c&&f++,r&&f++;let x=e[e.length-1].scrollY-e[0].scrollY;return{instantJumps:t,velocityVariance:u,momentumEvents:n,intervalVariance:h,scrollDirections:f,totalScrollY:x,exactPositionScrolls:a}}reset(){super.reset(),this.stopTracking(),this._scrollEvents=[]}};o(T,"id","scroll-behavior"),o(T,"category","behavior"),o(T,"weight",.5),o(T,"description","Detects programmatic scroll patterns"),o(T,"requiresInteraction",!0);var S=class extends m{async detect(){let e=[],t=0,n=navigator.plugins,i=navigator.mimeTypes;if(!n)return e.push("no-plugins-object"),t=Math.max(t,.6),this.createResult(!0,{anomalies:e},t);n.length===0&&(e.push("empty-plugins"),t=Math.max(t,.5));let s=navigator.userAgent||"";if(s.includes("Chrome")&&!s.includes("Chromium")&&!Array.from(n).some(p=>p.name.includes("PDF")||p.name.includes("Chromium PDF"))&&n.length===0&&(e.push("chrome-missing-pdf-plugin"),t=Math.max(t,.4)),n.length>0&&i){let a=0;for(let p=0;p<n.length;p++)a+=n[p].length||0;i.length===0&&a>0&&(e.push("mimetypes-mismatch"),t=Math.max(t,.5))}if(n.length>1){let a=Array.from(n).map(d=>d.name);new Set(a).size<a.length&&(e.push("duplicate-plugins"),t=Math.max(t,.6))}try{let a=Object.getOwnPropertyDescriptor(Navigator.prototype,"plugins");a&&a.get&&(a.get.toString().includes("[native code]")||(e.push("plugins-getter-overridden"),t=Math.max(t,.7)))}catch{}!/Android|iPhone|iPad|iPod|Mobile/i.test(s)&&n.length===1&&(e.push("minimal-plugins"),t=Math.max(t,.3));let r=e.length>0;return this.createResult(r,{anomalies:e,pluginCount:n.length,mimeTypeCount:(i==null?void 0:i.length)||0},t)}};o(S,"id","plugins"),o(S,"category","fingerprint"),o(S,"weight",.6),o(S,"description","Detects browser plugin anomalies");var L=class extends m{async detect(){let e=[],t=0,n=document.createElement("canvas"),i=null;try{i=n.getContext("webgl")||n.getContext("experimental-webgl")}catch{e.push("webgl-error"),t=Math.max(t,.5)}if(!i)return e.push("webgl-unavailable"),t=Math.max(t,.4),this.createResult(!0,{anomalies:e},t);let s=i.getExtension("WEBGL_debug_renderer_info"),c="",r="";s&&(c=i.getParameter(s.UNMASKED_VENDOR_WEBGL)||"",r=i.getParameter(s.UNMASKED_RENDERER_WEBGL)||""),!c&&!r&&(e.push("no-webgl-renderer-info"),t=Math.max(t,.6));let a=["swiftshader","llvmpipe","software","mesa","google swiftshader","vmware","virtualbox"],p=r.toLowerCase();for(let x of a)if(p.includes(x)){e.push(`suspicious-renderer-${x.replace(/\s+/g,"-")}`),t=Math.max(t,.7);break}c&&r&&(p.includes("nvidia")&&!c.toLowerCase().includes("nvidia")&&(e.push("vendor-renderer-mismatch"),t=Math.max(t,.6)),(p.includes("amd")||p.includes("radeon"))&&!c.toLowerCase().includes("amd")&&!c.toLowerCase().includes("ati")&&(e.push("vendor-renderer-mismatch"),t=Math.max(t,.6)));let d=i.getSupportedExtensions()||[];d.length<5&&(e.push("few-webgl-extensions"),t=Math.max(t,.4));let u=i.getParameter(i.MAX_TEXTURE_SIZE),l=i.getParameter(i.MAX_VIEWPORT_DIMS);(u<1024||u>65536)&&(e.push("unrealistic-max-texture"),t=Math.max(t,.5));try{i.clearColor(0,0,0,1),i.clear(i.COLOR_BUFFER_BIT);let x=new Uint8Array(4);i.readPixels(0,0,1,1,i.RGBA,i.UNSIGNED_BYTE,x),x[3]!==255&&(e.push("webgl-render-failure"),t=Math.max(t,.6))}catch{e.push("webgl-render-error"),t=Math.max(t,.5)}let h=i.getExtension("WEBGL_lose_context");h&&h.loseContext();let f=e.length>0;return this.createResult(f,{anomalies:e,vendor:c,renderer:r,extensionCount:d.length,maxTextureSize:u},t)}};o(L,"id","webgl"),o(L,"category","fingerprint"),o(L,"weight",.7),o(L,"description","Detects WebGL rendering anomalies");var P=class extends m{async detect(){let e=[],t=0;try{let i=document.createElement("canvas");i.width=200,i.height=50;let s=i.getContext("2d");if(!s)return e.push("canvas-context-unavailable"),t=Math.max(t,.5),this.createResult(!0,{anomalies:e},t);s.textBaseline="alphabetic",s.font="14px Arial",s.fillStyle="#f60",s.fillRect(0,0,200,50),s.fillStyle="#069",s.fillText("Bot Detection Test \u{1F916}",2,15),s.fillStyle="rgba(102, 204, 0, 0.7)",s.fillText("Canvas Fingerprint",4,30),s.beginPath(),s.arc(100,25,10,0,Math.PI*2,!0),s.closePath(),s.fill();let c=i.toDataURL();s.clearRect(0,0,200,50),s.fillStyle="#f60",s.fillRect(0,0,200,50),s.fillStyle="#069",s.fillText("Bot Detection Test \u{1F916}",2,15),s.fillStyle="rgba(102, 204, 0, 0.7)",s.fillText("Canvas Fingerprint",4,30),s.beginPath(),s.arc(100,25,10,0,Math.PI*2,!0),s.closePath(),s.fill();let r=i.toDataURL();c!==r&&(e.push("canvas-randomized"),t=Math.max(t,.6)),c.length<1e3&&(e.push("canvas-possibly-blank"),t=Math.max(t,.4));let a=document.createElement("canvas");a.width=200,a.height=50;let p=a.toDataURL();c===p&&(e.push("canvas-rendering-blocked"),t=Math.max(t,.7));try{i.toDataURL.toString().includes("[native code]")||(e.push("toDataURL-overridden"),t=Math.max(t,.8))}catch{}let u=s.getImageData(0,0,200,50).data,l=!0,h=[u[0],u[1],u[2],u[3]];for(let f=4;f<u.length;f+=4)if(u[f]!==h[0]||u[f+1]!==h[1]||u[f+2]!==h[2]){l=!1;break}l&&(e.push("uniform-pixel-data"),t=Math.max(t,.6))}catch{e.push("canvas-error"),t=Math.max(t,.4)}let n=e.length>0;return this.createResult(n,{anomalies:e},t)}};o(P,"id","canvas"),o(P,"category","fingerprint"),o(P,"weight",.5),o(P,"description","Detects canvas fingerprint anomalies");var I=class extends m{async detect(){let e=[],t=0,n=window.AudioContext||window.webkitAudioContext;if(!n)return e.push("audio-context-unavailable"),t=Math.max(t,.4),this.createResult(!0,{anomalies:e},t);let i=null,s=null,c=null;try{i=new n;let a=i.sampleRate;if(a!==44100&&a!==48e3&&a!==96e3&&(e.push("unusual-sample-rate"),t=Math.max(t,.3)),s=i.createOscillator(),c=i.createAnalyser(),!s||!c)e.push("audio-nodes-unavailable"),t=Math.max(t,.5);else{let d=c.fftSize,u=i.destination;(!u||u.maxChannelCount===0)&&(e.push("no-audio-destination"),t=Math.max(t,.6)),u&&u.maxChannelCount<2&&(e.push("mono-audio-only"),t=Math.max(t,.3))}try{n.toString().includes("[native code]")||(e.push("audio-context-overridden"),t=Math.max(t,.7))}catch{}try{if(i.state==="suspended"&&await i.resume().catch(()=>{}),i.state==="running"){let d=i.createOscillator(),u=i.createGain(),l=i.createScriptProcessor?i.createScriptProcessor(4096,1,1):null;l&&(d.type="triangle",d.frequency.value=1e4,u.gain.value=0,d.connect(u),u.connect(l),l.connect(i.destination),d.start(0),await new Promise(h=>setTimeout(h,50)),d.stop(),d.disconnect(),u.disconnect(),l.disconnect())}}catch{e.push("audio-fingerprint-blocked"),t=Math.max(t,.4)}window.OfflineAudioContext||window.webkitOfflineAudioContext||(e.push("offline-audio-context-unavailable"),t=Math.max(t,.3))}catch{e.push("audio-context-error"),t=Math.max(t,.4)}finally{if(s)try{s.disconnect()}catch{}if(c)try{c.disconnect()}catch{}if(i)try{i.close()}catch{}}let r=e.length>0;return this.createResult(r,{anomalies:e},t)}};o(I,"id","audio-context"),o(I,"category","fingerprint"),o(I,"weight",.5),o(I,"description","Detects AudioContext anomalies");var H=class extends m{async detect(){let e=[],t=0,n=window.screen;if(!n)return e.push("no-screen-object"),t=Math.max(t,.6),this.createResult(!0,{anomalies:e},t);let i=n.width,s=n.height,c=n.availWidth,r=n.availHeight,a=n.colorDepth,p=n.pixelDepth,d=window.outerWidth,u=window.outerHeight,l=window.innerWidth,h=window.innerHeight;(d===0||u===0)&&(e.push("zero-outer-dimensions"),t=Math.max(t,.8)),(l===0||h===0)&&(e.push("zero-inner-dimensions"),t=Math.max(t,.7));let f=navigator.userAgent||"";!/Android|iPhone|iPad|iPod|Mobile/i.test(f)&&(i<640||s<480)&&(e.push("very-small-screen"),t=Math.max(t,.5)),(i>7680||s>4320)&&(e.push("unrealistic-screen-size"),t=Math.max(t,.4));let _=[{w:800,h:600},{w:1024,h:768},{w:1920,h:1080}];for(let v of _)if(i===v.w&&s===v.h&&d===v.w&&u===v.h){e.push("headless-default-dimensions"),t=Math.max(t,.5);break}(c>i||r>s)&&(e.push("available-exceeds-total"),t=Math.max(t,.7)),(d>i||u>s)&&(e.push("window-exceeds-screen"),t=Math.max(t,.6)),a!==24&&a!==32&&a!==30&&a!==48&&(e.push("unusual-color-depth"),t=Math.max(t,.3)),a!==p&&(e.push("depth-mismatch"),t=Math.max(t,.3));let w=window.devicePixelRatio;if(w===0||w===void 0?(e.push("missing-device-pixel-ratio"),t=Math.max(t,.5)):(w<.5||w>5)&&(e.push("unusual-device-pixel-ratio"),t=Math.max(t,.4)),n.orientation){let v=n.orientation.type,W=n.orientation.angle;v.includes("landscape")&&i<s&&(e.push("orientation-dimension-mismatch"),t=Math.max(t,.4)),v.includes("portrait")&&i>s&&(e.push("orientation-dimension-mismatch"),t=Math.max(t,.4))}l===d&&h===u&&d>0&&u>0&&(e.push("no-browser-chrome"),t=Math.max(t,.5));let k=e.length>0;return this.createResult(k,{anomalies:e,dimensions:{screen:{width:i,height:s},available:{width:c,height:r},window:{outer:{width:d,height:u},inner:{width:l,height:h}},colorDepth:a,devicePixelRatio:w}},t)}};o(H,"id","screen"),o(H,"category","fingerprint"),o(H,"weight",.4),o(H,"description","Detects unusual screen dimensions");var A=class extends m{async detect(){let e=[],t=0;if(!window.performance||!performance.timing){if(performance.getEntriesByType){let v=performance.getEntriesByType("navigation");if(v.length>0)return this._analyzeNavigationTiming(v[0])}return e.push("no-performance-api"),t=Math.max(t,.3),this.createResult(!0,{anomalies:e},t)}let n=performance.timing,i=n.navigationStart,s=n.domContentLoadedEventEnd-i,c=n.domComplete-i,r=n.loadEventEnd-i,a=n.domainLookupEnd-n.domainLookupStart,p=n.connectEnd-n.connectStart,d=n.responseEnd-n.requestStart,u=n.domComplete-n.domLoading;s>0&&s<10&&(e.push("instant-dom-content-loaded"),t=Math.max(t,.7)),a===0&&p===0&&d<5&&(e.push("zero-network-timing"),t=Math.max(t,.4)),(s<0||c<0||r<0)&&(e.push("negative-timing"),t=Math.max(t,.8)),n.domContentLoadedEventEnd>0&&n.loadEventEnd>0&&n.domContentLoadedEventEnd>n.loadEventEnd&&(e.push("timing-order-violation"),t=Math.max(t,.7)),u>3e4&&(e.push("excessive-dom-processing"),t=Math.max(t,.3));let l=n.domContentLoadedEventStart-n.responseEnd;l>0&&l<5&&(e.push("instant-script-execution"),t=Math.max(t,.4));let h=performance.now(),f=performance.now();h===f&&h>0&&(e.push("frozen-performance-now"),t=Math.max(t,.6));let x=Date.now(),_=performance.now(),w=Date.now();Math.abs(w-x-(performance.now()-_))>100&&(e.push("timing-inconsistency"),t=Math.max(t,.5));let k=e.length>0;return this.createResult(k,{anomalies:e,timings:{domContentLoaded:s,domComplete:c,loadComplete:r,dnsLookup:a,tcpConnection:p,serverResponse:d,domProcessing:u}},t)}_analyzeNavigationTiming(e){let t=[],n=0,i=e.domContentLoadedEventEnd,s=e.loadEventEnd,c=e.domainLookupEnd-e.domainLookupStart,r=e.responseEnd-e.requestStart;i>0&&i<10&&(t.push("instant-dom-content-loaded"),n=Math.max(n,.7)),c===0&&r===0&&(t.push("zero-network-timing"),n=Math.max(n,.4));let a=t.length>0;return this.createResult(a,{anomalies:t,timings:{domContentLoaded:i,loadComplete:s,dnsLookup:c,serverResponse:r}},n)}};o(A,"id","page-load"),o(A,"category","timing"),o(A,"weight",.5),o(A,"description","Detects suspicious page load timing");var O=class extends m{constructor(e={}){super(e),this._domContentLoadedTime=null,this._documentReadyState=document.readyState,this._captureTime=performance.now(),document.readyState==="loading"&&document.addEventListener("DOMContentLoaded",()=>{this._domContentLoadedTime=performance.now()})}async detect(){let e=[],t=0,n=performance.now(),i=document.readyState,s=0,c=0,r=0;if(performance.getEntriesByType){let p=performance.getEntriesByType("resource");s=p.length;for(let d of p)c+=d.duration,d.initiatorType==="script"&&d.name.startsWith("http")&&r++}s===0&&i==="complete"&&(e.push("no-resources-loaded"),t=Math.max(t,.4)),this._domContentLoadedTime&&this._domContentLoadedTime<50&&s===0&&(e.push("instant-ready-no-resources"),t=Math.max(t,.6)),document.hidden&&this._documentReadyState==="loading"&&(e.push("hidden-at-load"),t=Math.max(t,.3)),typeof document.visibilityState>"u"&&(e.push("no-visibility-api"),t=Math.max(t,.4));try{let p=performance.now(),d=document.createElement("div");d.id="__bot_detection_test__",document.body.appendChild(d);let u=performance.now();document.body.removeChild(d);let l=performance.now(),h=u-p,f=l-u;h===0&&f===0&&(e.push("instant-dom-operations"),t=Math.max(t,.5))}catch{document.body||(e.push("no-document-body"),t=Math.max(t,.4))}if(typeof MutationObserver>"u"&&(e.push("no-mutation-observer"),t=Math.max(t,.5)),typeof requestAnimationFrame>"u"&&(e.push("no-request-animation-frame"),t=Math.max(t,.5)),performance.getEntriesByType){let p=performance.getEntriesByType("paint");!p.find(l=>l.name==="first-paint")&&i==="complete"&&n>1e3&&(e.push("no-first-paint"),t=Math.max(t,.4)),!p.find(l=>l.name==="first-contentful-paint")&&i==="complete"&&n>1e3&&(e.push("no-first-contentful-paint"),t=Math.max(t,.4))}typeof IntersectionObserver>"u"&&(e.push("no-intersection-observer"),t=Math.max(t,.4));let a=e.length>0;return this.createResult(a,{anomalies:e,metrics:{readyState:i,resourceCount:s,externalScriptCount:r,domContentLoadedTime:this._domContentLoadedTime,documentHidden:document.hidden}},t)}};o(O,"id","dom-content-timing"),o(O,"category","timing"),o(O,"weight",.4),o(O,"description","Analyzes DOM content loaded timing patterns");var B=class extends m{async detect(){let e=[],t=0;window.__puppeteer_evaluation_script__&&(e.push("puppeteer-evaluation-script"),t=Math.max(t,1));let n=["__puppeteer_evaluation_script__","__puppeteer","puppeteer"];for(let r of n)r in window&&(e.push(`global-${r}`),t=Math.max(t,1));(navigator.userAgent||"").includes("HeadlessChrome")&&(e.push("headless-chrome-ua"),t=Math.max(t,.9)),(window.cdc_adoQpoasnfa76pfcZLmcfl_Array||window.cdc_adoQpoasnfa76pfcZLmcfl_Promise||window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol)&&(e.push("cdp-artifacts"),t=Math.max(t,1));try{window.eval.toString().includes("puppeteer")&&(e.push("eval-puppeteer"),t=Math.max(t,.9))}catch{}try{throw new Error("stack trace test")}catch(r){let a=r.stack||"";(a.includes("puppeteer")||a.includes("pptr"))&&(e.push("stack-trace-puppeteer"),t=Math.max(t,.8))}window.innerWidth===800&&window.innerHeight===600&&(e.push("default-viewport"),t=Math.max(t,.3)),navigator.webdriver===!0&&(e.push("webdriver-flag"),t=Math.max(t,.9)),Object.keys(window).filter(r=>r.startsWith("__")&&typeof window[r]=="function").length>3&&(e.push("suspicious-bindings"),t=Math.max(t,.5)),typeof window.chrome<"u"&&(!window.chrome.runtime||!window.chrome.runtime.id)&&(e.push("incomplete-chrome-object"),t=Math.max(t,.4));let c=e.length>0;return this.createResult(c,{indicators:e},t)}};o(B,"id","puppeteer"),o(B,"category","automation"),o(B,"weight",1),o(B,"description","Detects Puppeteer automation artifacts");var V=class extends m{async detect(){let e=[],t=0;window.__playwright&&(e.push("playwright-namespace"),t=Math.max(t,1));let n=["__playwright","__pw_manual","__pwInitScripts","playwright"];for(let c of n)c in window&&(e.push(`global-${c}`),t=Math.max(t,1));window.__playwright__binding__&&(e.push("playwright-binding"),t=Math.max(t,1));let i=navigator.userAgent||"";(i.includes("Playwright")||i.includes("HeadlessChrome"))&&(e.push("playwright-ua-marker"),t=Math.max(t,i.includes("Playwright")?1:.7)),navigator.webdriver===!0&&(e.push("webdriver-flag"),t=Math.max(t,.8));try{Object.keys(window).filter(a=>a.startsWith("__pw")).length>0&&(e.push("pw-bindings"),t=Math.max(t,1))}catch{}typeof window.__pw_date_intercepted<"u"&&(e.push("date-interception"),t=Math.max(t,.9)),window.__pw_geolocation__&&(e.push("geolocation-mock"),t=Math.max(t,.9)),window.__pw_permissions__&&(e.push("permissions-override"),t=Math.max(t,.9)),window.__cdpSession__&&(e.push("cdp-session"),t=Math.max(t,.8));try{throw new Error("stack trace test")}catch(c){let r=c.stack||"";(r.includes("playwright")||r.includes("__pw"))&&(e.push("stack-trace-playwright"),t=Math.max(t,.8))}try{let r=new Date().toLocaleString();window.__pwTimezone__&&(e.push("timezone-mock"),t=Math.max(t,.8))}catch{}let s=e.length>0;return this.createResult(s,{indicators:e},t)}};o(V,"id","playwright"),o(V,"category","automation"),o(V,"weight",1),o(V,"description","Detects Playwright automation artifacts");var K=class extends m{async detect(){let e=[],t=0;navigator.webdriver===!0&&(e.push("webdriver-flag"),t=Math.max(t,1));let n=["_selenium","callSelenium","_Selenium_IDE_Recorder","__selenium_evaluate","__selenium_unwrap","__webdriver_evaluate","__webdriver_unwrap","__webdriver_script_function","__webdriver_script_func","__fxdriver_evaluate","__fxdriver_unwrap","webdriver"];for(let a of n)a in window&&(e.push(`global-${a}`),t=Math.max(t,1));let i=["__webdriver_script_fn","__driver_evaluate","__webdriver_evaluate","__selenium_evaluate","__fxdriver_evaluate","__driver_unwrap","__webdriver_unwrap","__selenium_unwrap","__fxdriver_unwrap"];for(let a of i)a in document&&(e.push(`document-${a}`),t=Math.max(t,1));Object.keys(window).filter(a=>a.startsWith("$cdc_")||a.startsWith("$wdc_")||a.startsWith("$chrome_asyncScriptInfo")).length>0&&(e.push("chromedriver-variables"),t=Math.max(t,1)),(window.webdriverCallback||document.documentElement.getAttribute("webdriver"))&&(e.push("geckodriver-artifacts"),t=Math.max(t,1));try{let a=document.documentElement;(a.hasAttribute("webdriver")||a.getAttribute("selenium")||a.getAttribute("driver"))&&(e.push("document-webdriver-attr"),t=Math.max(t,1))}catch{}(window.selenium||window.sideex)&&(e.push("selenium-ide"),t=Math.max(t,1));try{let a=Object.getOwnPropertyDescriptor(Navigator.prototype,"webdriver");a&&a.get&&(a.get.toString().includes("[native code]")||(e.push("webdriver-getter-modified"),t=Math.max(t,.7)))}catch{}(window.domAutomation||window.domAutomationController)&&(e.push("dom-automation"),t=Math.max(t,1)),window.awesomium&&(e.push("awesomium"),t=Math.max(t,.9)),window.external&&window.external.toString().includes("Selenium")&&(e.push("external-selenium"),t=Math.max(t,1));let r=e.length>0;return this.createResult(r,{indicators:e},t)}};o(K,"id","selenium"),o(K,"category","automation"),o(K,"weight",1),o(K,"description","Detects Selenium WebDriver artifacts");var q=class extends m{async detect(){let e=[],t=0;window.callPhantom&&(e.push("callPhantom"),t=Math.max(t,1)),window._phantom&&(e.push("_phantom"),t=Math.max(t,1)),window.phantom&&(e.push("phantom"),t=Math.max(t,1));let n=navigator.userAgent||"";n.includes("PhantomJS")&&(e.push("phantomjs-ua"),t=Math.max(t,1)),window.__phantomas&&(e.push("phantomas"),t=Math.max(t,1)),window.__casper&&(e.push("casperjs"),t=Math.max(t,1)),window.casper&&(e.push("casper-global"),t=Math.max(t,1)),window.slimer&&(e.push("slimerjs"),t=Math.max(t,1)),window.__nightmare&&(e.push("nightmare"),t=Math.max(t,1)),window.nightmare&&(e.push("nightmare-global"),t=Math.max(t,1));try{let c=Function.prototype.toString.call(Function);(c.includes("phantom")||c.includes("Phantom"))&&(e.push("function-prototype-phantom"),t=Math.max(t,.8))}catch{}try{throw new Error("test")}catch(c){(c.stack||"").includes("phantom")&&(e.push("stack-trace-phantom"),t=Math.max(t,.9))}navigator.plugins&&navigator.plugins.length===0&&e.length>0&&(e.push("no-plugins-phantom"),t=Math.max(t,.5));let i=["__PHANTOM__","PHANTOM","Buffer","process"];for(let c of i)c in window&&c!=="Buffer"&&c!=="process"&&(e.push(`phantom-prop-${c.toLowerCase()}`),t=Math.max(t,.9));n.includes("QtWebKit")&&(e.push("qtwebkit"),t=Math.max(t,.7));let s=e.length>0;return this.createResult(s,{indicators:e},t)}};o(q,"id","phantomjs"),o(q,"category","automation"),o(q,"weight",1),o(q,"description","Detects PhantomJS automation artifacts");var tt={WebDriverSignal:E,HeadlessSignal:C,NavigatorAnomalySignal:R,PermissionsSignal:D,MouseMovementSignal:y,KeyboardPatternSignal:M,InteractionTimingSignal:b,ScrollBehaviorSignal:T,PluginsSignal:S,WebGLSignal:L,CanvasSignal:P,AudioContextSignal:I,ScreenSignal:H,PageLoadSignal:A,DOMContentTimingSignal:O,PuppeteerSignal:B,PlaywrightSignal:V,SeleniumSignal:K,PhantomJSSignal:q},G=[new E,new C,new R,new D,new S,new L,new P,new I,new H,new A,new O,new B,new V,new K,new q],Q=[new y,new M,new b,new T],lt=[...G,...Q];function Z(g={}){let{includeInteractionSignals:e=!0,instantBotSignals:t=["webdriver","puppeteer","playwright","selenium","phantomjs"],...n}=g,i=e?[...G,...Q.map(s=>{let c=s.constructor;return new c(s.options)})]:G.map(s=>{let c=s.constructor;return new c(s.options)});return new j({signals:i,instantBotSignals:t,...n})}async function J(g={}){return Z({includeInteractionSignals:!g.skipInteractionSignals}).detect(g)}async function et(){return J({skipInteractionSignals:!0})}var ut={BotDetector:j,createDetector:Z,detect:J,detectInstant:et,Signal:m,Signals:tt,Verdict:z};return ht(dt);})();
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@niksbanna/bot-detector",
3
+ "version": "1.0.0",
4
+ "description": "Production-grade client-side bot detection system using signal-based scoring",
5
+ "main": "dist/bot-detector.cjs.js",
6
+ "module": "dist/bot-detector.esm.js",
7
+ "browser": "dist/bot-detector.iife.js",
8
+ "types": "dist/types.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/types.d.ts",
12
+ "browser": "./dist/bot-detector.iife.js",
13
+ "import": "./dist/bot-detector.esm.js",
14
+ "require": "./dist/bot-detector.cjs.js",
15
+ "default": "./dist/bot-detector.esm.js"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "src",
21
+ "README.md"
22
+ ],
23
+ "scripts": {
24
+ "build": "node esbuild.config.js",
25
+ "dev": "node esbuild.config.js --watch",
26
+ "test": "vitest run",
27
+ "test:watch": "vitest",
28
+ "test:coverage": "vitest run --coverage",
29
+ "lint": "eslint src/",
30
+ "prepublishOnly": "npm run build"
31
+ },
32
+ "keywords": [
33
+ "bot-detection",
34
+ "anti-bot",
35
+ "fingerprinting",
36
+ "browser-detection",
37
+ "automation-detection",
38
+ "security",
39
+ "fraud-prevention"
40
+ ],
41
+ "author": "niksbanna",
42
+ "license": "MIT",
43
+ "devDependencies": {
44
+ "esbuild": "^0.25.0",
45
+ "vitest": "^3.0.0",
46
+ "@vitest/coverage-v8": "^3.0.0",
47
+ "happy-dom": "^20.3.0",
48
+ "eslint": "^9.18.0"
49
+ },
50
+ "engines": {
51
+ "node": ">=16.0.0"
52
+ },
53
+ "repository": {
54
+ "type": "git",
55
+ "url": ""
56
+ }
57
+ }