Skip to content

Commit 33bb579

Browse files
committed
classify API
1 parent f2322c0 commit 33bb579

File tree

1 file changed

+64
-202
lines changed

1 file changed

+64
-202
lines changed

dist/privacy.js

Lines changed: 64 additions & 202 deletions
Original file line numberDiff line numberDiff line change
@@ -297,283 +297,145 @@ let sync_metrics = {
297297
})(),
298298

299299
fingerprinting: (() => {
300-
// These are determined by looking at the tests in https://github.com/fingerprintjs/fingerprintjs
301-
const fingerprintingAPIs = [
300+
// The APIs are determined by looking at the tests in https://github.com/fingerprintjs/fingerprintjs and https://amiunique.org/fingerprint
301+
// Grouped by unique API to improve diversity metric reliability
302+
const fingerprintingAPIs = {
302303
// Payment APIs
303-
'ApplePaySession\.canMakePayments',
304+
'payment': 'ApplePaySession\.canMakePayments',
304305

305306
// User Agent and Platform fingerprinting
306-
'navigator\.userAgent',
307-
'navigator\.platform',
308-
'navigator\.oscpu',
309-
'navigator\.vendor',
310-
'navigator\.vendorSub',
311-
'navigator\.product',
312-
'navigator\.productSub',
313-
'navigator\.buildID',
307+
'navigator_userAgent': 'navigator\.userAgent',
308+
'navigator_platform': 'navigator\.platform',
309+
'navigator_oscpu': 'navigator\.oscpu',
310+
'navigator_vendor': 'navigator\.(vendor|vendorSub)',
311+
'navigator_product': 'navigator\.(product|productSub)',
312+
'navigator_buildID': 'navigator\.buildID',
314313

315314
// Audio fingerprinting
316-
'createAnalyser',
317-
'createOscillator',
318-
'createScriptProcessor',
319-
'getChannelData',
320-
'getFloatFrequencyData',
321-
'getByteFrequencyData',
322-
'OscillatorNode',
323-
'AudioContext',
324-
'webkitAudioContext',
325-
'AnalyserNode',
326-
'createDynamicsCompressor',
327-
'channelCount',
328-
'channelCountMode',
329-
'channelInterpretation',
330-
'fftSize',
331-
'frequencyBinCount',
332-
'maxDecibels',
333-
'minDecibels',
334-
'smoothingTimeConstant',
335-
'sampleRate',
315+
'audio_context': '(AudioContext|webkitAudioContext)',
316+
'audio_analysis': '(createAnalyser|AnalyserNode|getFloatFrequencyData|getByteFrequencyData|fftSize|frequencyBinCount|maxDecibels|minDecibels|smoothingTimeConstant)',
317+
'audio_processing': '(createOscillator|OscillatorNode|createScriptProcessor|createDynamicsCompressor)',
318+
'audio_data': '(getChannelData|channelCount|channelCountMode|channelInterpretation|sampleRate)',
336319

337320
// Canvas fingerprinting
338-
'canvas\.getContext',
339-
'canvas\.toDataURL',
340-
'canvasRenderingContext2D\.fillText',
341-
'canvasRenderingContext2D\.strokeText',
342-
'canvasRenderingContext2D\.getImageData',
343-
'HTMLCanvasElement\.toBlob',
344-
'getContext\(.*2d.*\)',
345-
'getContext\(.*webgl.*\)',
321+
'canvas_context': 'canvas\.getContext|getContext\(.*(2d|webgl).*\)',
322+
'canvas_rendering': '(canvasRenderingContext2D\.(fillText|strokeText|getImageData)|canvas\.toDataURL|HTMLCanvasElement\.toBlob)',
346323

347324
// CSS media queries for fingerprinting
348-
'@media.*color-gamut',
349-
'@media.*prefers-contrast',
350-
'@media.*forced-colors',
351-
'@media.*dynamic-range',
352-
'@media.*inverted-colors',
353-
'@media.*min-monochrome',
354-
'@media.*max-monochrome',
355-
'@media.*prefers-reduced-motion',
356-
'@media.*prefers-reduced-transparency',
325+
'css_media_queries': '@media.*(color-gamut|prefers-contrast|forced-colors|dynamic-range|inverted-colors|min-monochrome|max-monochrome|prefers-reduced-motion|prefers-reduced-transparency)',
357326

358327
// Hardware fingerprinting
359-
'cpuClass',
360-
'deviceMemory',
361-
'hardwareConcurrency',
362-
'maxTouchPoints',
363-
'ontouchstart',
328+
'hardware_info': '(cpuClass|deviceMemory|hardwareConcurrency|maxTouchPoints)',
329+
330+
// Touch capabilities
331+
'touch_capabilities': '(ontouchstart|TouchEvent|createTouch|createTouchList)',
364332

365333
// Storage APIs (potential fingerprinting)
366-
'indexedDB',
367-
'localStorage',
368-
'sessionStorage',
369-
'openDatabase',
334+
'storage_apis': '(indexedDB|localStorage|sessionStorage|openDatabase)',
370335

371336
// PDF and plugins
372-
'pdfViewerEnabled',
373-
'navigator\.plugins',
374-
'navigator\.mimeTypes',
375-
'Plugin\s',
376-
'MimeType',
337+
'plugins': '(pdfViewerEnabled|navigator\.(plugins|mimeTypes)|Plugin\s|MimeType)',
377338

378339
// Attribution and tracking
379-
'attributionSourceId',
340+
'attribution': 'attributionSourceId',
380341

381342
// Time zone and language fingerprinting
382-
'resolvedOptions\(\)\.timeZone',
383-
'getTimezoneOffset',
384-
'navigator\.language',
385-
'navigator\.languages',
386-
'Intl\.DateTimeFormat',
387-
'Intl\.Collator',
343+
'timezone': '(resolvedOptions\(\)\.timeZone|getTimezoneOffset)',
344+
'language': '(navigator\.(language|languages)|Intl\.(DateTimeFormat|Collator))',
388345

389346
// WebGL fingerprinting
390-
'vendorUnmasked',
391-
'rendererUnmasked',
392-
'shadingLanguageVersion',
393-
'WEBGL_debug_renderer_info',
394-
'getShaderPrecisionFormat',
395-
'WebGLRenderingContext',
396-
'getParameter',
397-
'getSupportedExtensions',
398-
'getExtension',
399-
'VENDOR',
400-
'RENDERER',
401-
'VERSION',
402-
'SHADING_LANGUAGE_VERSION',
347+
'webgl_info': '(vendorUnmasked|rendererUnmasked|shadingLanguageVersion|WEBGL_debug_renderer_info|WebGLRenderingContext)',
348+
'webgl_params': '(getShaderPrecisionFormat|getParameter|getSupportedExtensions|getExtension|VENDOR|RENDERER|VERSION|SHADING_LANGUAGE_VERSION)',
403349

404350
// Screen properties
405-
'availWidth',
406-
'availHeight',
407-
'screen\.width',
408-
'screen\.height',
409-
'screen\.colorDepth',
410-
'screen\.pixelDepth',
411-
'screen\.availTop',
412-
'screen\.availLeft',
413-
'outerWidth',
414-
'outerHeight',
415-
'innerWidth',
416-
'innerHeight',
417-
'devicePixelRatio',
351+
'screen_properties': '(availWidth|availHeight)|screen\.(width|height|colorDepth|pixelDepth|availTop|availLeft)|(outerWidth|outerHeight|innerWidth|innerHeight)|devicePixelRatio',
418352

419353
// Window and browser chrome fingerprinting
420-
'locationbar',
421-
'menubar',
422-
'personalbar',
423-
'scrollbars',
424-
'statusbar',
425-
'toolbar',
426-
'history\.length',
427-
428-
// Geolocation API: https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API
429-
'getCurrentPosition',
430-
'watchPosition',
431-
'navigator\.geolocation',
354+
'browser_chrome': '(locationbar|menubar|personalbar|scrollbars|statusbar|toolbar|history\.length)',
355+
356+
// Geolocation API
357+
'geolocation': '(getCurrentPosition|watchPosition|navigator\.geolocation)',
432358

433359
// Media devices and capabilities
434-
'enumerateDevices',
435-
'getUserMedia',
436-
'getDisplayMedia',
437-
'navigator\.mediaDevices',
438-
'canPlayType',
439-
'HTMLVideoElement\.canPlayType',
440-
'HTMLAudioElement\.canPlayType',
360+
'media_devices': '(enumerateDevices|getUserMedia|getDisplayMedia|navigator\.mediaDevices)',
361+
'media_capabilities': '(canPlayType|HTMLVideoElement\.canPlayType|HTMLAudioElement\.canPlayType)',
441362

442363
// Permissions API
443-
'navigator\.permissions',
444-
'permissions\.query',
364+
'permissions': '(navigator\.permissions|permissions\.query)',
445365

446366
// Battery API
447-
'navigator\.battery',
448-
'navigator\.getBattery',
449-
'charging',
450-
'chargingTime',
451-
'dischargingTime',
452-
// 'level',
367+
'battery': '(navigator\.(battery|getBattery)|charging|chargingTime|dischargingTime)',
453368

454369
// Connection API
455-
'navigator\.connection',
456-
'navigator\.mozConnection',
457-
'navigator\.webkitConnection',
458-
'downlink',
459-
'effectiveType',
460-
// 'rtt',
461-
// 'saveData',
370+
'connection': '(navigator\.(connection|mozConnection|webkitConnection)|downlink|effectiveType)',
462371

463372
// Sensors APIs
464-
'Accelerometer',
465-
'Gyroscope',
466-
'LinearAccelerationSensor',
467-
'AbsoluteOrientationSensor',
468-
'RelativeOrientationSensor',
469-
'AmbientLightSensor',
470-
'ProximitySensor',
471-
472-
// Touch and input
473-
'TouchEvent',
474-
'createTouch',
475-
'createTouchList',
373+
'sensors': '(Accelerometer|Gyroscope|LinearAccelerationSensor|AbsoluteOrientationSensor|RelativeOrientationSensor|AmbientLightSensor|ProximitySensor)',
476374

477375
// Font detection
478-
'document\.fonts',
479-
'FontFace',
376+
'fonts': '(document\.fonts|FontFace)',
480377

481378
// Do Not Track
482-
'navigator\.doNotTrack',
483-
'window\.doNotTrack',
379+
'do_not_track': '(navigator\.doNotTrack|window\.doNotTrack)',
484380

485381
// Cookie detection
486-
'navigator\.cookieEnabled',
382+
'cookies': 'navigator\.cookieEnabled',
487383

488384
// Java detection
489-
'navigator\.javaEnabled',
385+
'java': 'navigator\.javaEnabled',
386+
387+
// WebRTC
388+
'webrtc_peer': '(RTCPeerConnection|webkitRTCPeerConnection|mozRTCPeerConnection)',
389+
'webrtc_data': '(RTCDataChannel|createDataChannel)',
490390

491-
// Additional modern fingerprinting vectors
492-
'RTCPeerConnection',
493-
'webkitRTCPeerConnection',
494-
'mozRTCPeerConnection',
495-
'performance\.memory',
496-
'performance\.timing',
497-
'Notification\.permission',
391+
// Performance APIs
392+
'performance': '(performance\.(memory|timing))',
393+
394+
// Notifications
395+
'notifications': 'Notification\.permission',
498396

499397
// Keyboard layout detection
500-
'KeyboardLayoutMap',
501-
'navigator\.keyboard',
502-
'getLayoutMap',
398+
'keyboard': '(KeyboardLayoutMap|navigator\.keyboard|getLayoutMap)',
503399

504400
// Gamepad API
505-
'navigator\.getGamepads',
506-
'GamepadEvent',
401+
'gamepad': '(navigator\.getGamepads|GamepadEvent)',
507402

508403
// Storage quota
509-
'navigator\.storage',
510-
'navigator\.webkitTemporaryStorage',
511-
'navigator\.webkitPersistentStorage',
512-
'estimate',
404+
'storage_quota': '(navigator\.(storage|webkitTemporaryStorage|webkitPersistentStorage)|estimate)',
513405

514406
// Speech APIs
515-
'SpeechSynthesis',
516-
'SpeechRecognition',
517-
518-
// WebRTC Data Channel
519-
'RTCDataChannel',
520-
'createDataChannel',
407+
'speech': '(SpeechSynthesis|SpeechRecognition)',
521408

522409
// Crypto subtle fingerprinting
523-
'crypto\.subtle',
524-
'SubtleCrypto',
410+
'crypto': '(crypto\.subtle|SubtleCrypto)',
525411

526412
// Worker capabilities
527-
'Worker',
528-
'SharedWorker',
529-
'ServiceWorker'
530-
];
413+
'workers': '(Worker|SharedWorker|ServiceWorker)'
414+
};
531415

532416
// Pre-compile regexes - handle already escaped patterns
533-
const compiledRegexes = fingerprintingAPIs.map(api => ({
534-
api,
535-
regex: new RegExp(api, 'gi')
417+
const compiledRegexes = Object.entries(fingerprintingAPIs).map(([apiName, pattern]) => ({
418+
api: apiName,
419+
regex: new RegExp(pattern, 'gi')
536420
}));
537421
let likelyFingerprintingScripts = [];
538422

539423
response_bodies.forEach(req => {
540424
try {
541425
let detectedApis = [];
542-
let totalOccurrences = 0;
543-
let body = req.response_body;
544-
545-
// Validate response body
546-
if (!body || typeof body !== 'string') {
547-
return; // Skip invalid response bodies
548-
}
549426

550427
compiledRegexes.forEach(({ api, regex }) => {
551428
try {
552-
// Reset regex index for global regex
553-
regex.lastIndex = 0;
554-
555-
// Use a more memory-efficient counting approach
556-
let match;
557-
let matches = 0;
558-
while ((match = regex.exec(body)) !== null) {
559-
matches++;
560-
// Prevent infinite loops on zero-length matches
561-
if (match.index === regex.lastIndex) {
562-
regex.lastIndex++;
563-
}
564-
}
565-
566-
if (matches > 0) {
429+
if (regex.test(req.response_body)) {
567430
detectedApis.push(api);
568-
totalOccurrences += matches;
569431
}
570432
} catch (regexError) {
571433
// Skip this API on regex error - avoid console.warn in WebPageTest
572434
}
573435
});
574436

575437
// Track scripts with significant fingerprinting API usage
576-
if (detectedApis.length >= 5 ) {
438+
if (detectedApis.length >= 5) {
577439
likelyFingerprintingScripts.push({
578440
url: req.url,
579441
detectedApis

0 commit comments

Comments
 (0)