mirror of
https://github.com/smittix/intercept.git
synced 2026-04-28 16:50:01 -07:00
Add comprehensive BLE tracker detection with signature engine
Implement reliable tracker detection for AirTag, Tile, Samsung SmartTag, and other BLE trackers based on manufacturer data patterns, service UUIDs, and advertising payload analysis. Key changes: - Add TrackerSignatureEngine with signatures for major tracker brands - Device fingerprinting to track devices across MAC randomization - Suspicious presence heuristics (persistence, following patterns) - New API endpoints: /api/bluetooth/trackers, /diagnostics - UI updates with tracker badges, confidence, and evidence display - TSCM integration updated to use v2 tracker detection data - Unit tests and smoke test scripts for validation Detection is heuristic-based with confidence scoring (high/medium/low) and evidence transparency. Backwards compatible with existing APIs. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -206,6 +206,8 @@ class ThreatDetector:
|
||||
"""
|
||||
Classify a Bluetooth device into informational/review/high_interest.
|
||||
|
||||
Now uses the v2 tracker detection data if available.
|
||||
|
||||
Returns:
|
||||
Dict with 'classification', 'reasons', and metadata
|
||||
"""
|
||||
@@ -217,7 +219,6 @@ class ThreatDetector:
|
||||
|
||||
reasons = []
|
||||
classification = 'informational'
|
||||
tracker_info = None
|
||||
|
||||
# Track repeat detections
|
||||
times_seen = _record_device_seen(f'bt:{mac}') if mac else 1
|
||||
@@ -225,8 +226,25 @@ class ThreatDetector:
|
||||
# Check if in baseline (known device)
|
||||
in_baseline = mac in self.baseline_bt_macs if self.baseline else False
|
||||
|
||||
# Check for trackers (do this early for all devices)
|
||||
tracker_info = is_known_tracker(name, manufacturer_data)
|
||||
# Use v2 tracker detection data if available (from get_tscm_bluetooth_snapshot)
|
||||
tracker_data = device.get('tracker', {})
|
||||
is_tracker_v2 = tracker_data.get('is_tracker', False)
|
||||
tracker_type_v2 = tracker_data.get('type')
|
||||
tracker_name_v2 = tracker_data.get('name')
|
||||
tracker_confidence_v2 = tracker_data.get('confidence')
|
||||
tracker_evidence_v2 = tracker_data.get('evidence', [])
|
||||
|
||||
# Use v2 risk analysis if available
|
||||
risk_data = device.get('risk_analysis', {})
|
||||
risk_score = risk_data.get('risk_score', 0)
|
||||
risk_factors = risk_data.get('risk_factors', [])
|
||||
|
||||
# Fall back to legacy detection if v2 not available
|
||||
tracker_info_legacy = None
|
||||
if not is_tracker_v2:
|
||||
tracker_info_legacy = is_known_tracker(name, manufacturer_data)
|
||||
|
||||
is_tracker = is_tracker_v2 or (tracker_info_legacy is not None)
|
||||
|
||||
if in_baseline:
|
||||
reasons.append('Known device in baseline')
|
||||
@@ -241,8 +259,24 @@ class ThreatDetector:
|
||||
classification = 'review'
|
||||
|
||||
# Check for trackers -> high interest
|
||||
if tracker_info:
|
||||
reasons.append(f"Known tracker: {tracker_info.get('name', 'Unknown')}")
|
||||
if is_tracker_v2:
|
||||
tracker_label = tracker_name_v2 or tracker_type_v2 or 'Unknown tracker'
|
||||
conf_label = f' ({tracker_confidence_v2})' if tracker_confidence_v2 else ''
|
||||
reasons.append(f"Tracker detected: {tracker_label}{conf_label}")
|
||||
classification = 'high_interest'
|
||||
|
||||
# Add evidence from v2 detection
|
||||
for evidence_item in tracker_evidence_v2[:2]: # First 2 items
|
||||
reasons.append(f"Evidence: {evidence_item}")
|
||||
|
||||
# Add risk factors if significant
|
||||
if risk_score >= 0.3:
|
||||
reasons.append(f"Risk score: {int(risk_score * 100)}%")
|
||||
for factor in risk_factors[:2]: # First 2 factors
|
||||
reasons.append(f"Risk: {factor}")
|
||||
|
||||
elif tracker_info_legacy:
|
||||
reasons.append(f"Known tracker: {tracker_info_legacy.get('name', 'Unknown')}")
|
||||
classification = 'high_interest'
|
||||
|
||||
# Check for audio-capable devices -> high interest
|
||||
@@ -268,6 +302,10 @@ class ThreatDetector:
|
||||
classification = 'high_interest'
|
||||
|
||||
# Include standardized signal classification
|
||||
try:
|
||||
rssi_val = int(rssi) if rssi else -100
|
||||
except (ValueError, TypeError):
|
||||
rssi_val = -100
|
||||
signal_info = get_signal_strength_info(rssi_val)
|
||||
|
||||
return {
|
||||
@@ -275,7 +313,11 @@ class ThreatDetector:
|
||||
'reasons': reasons,
|
||||
'in_baseline': in_baseline,
|
||||
'times_seen': times_seen,
|
||||
'is_tracker': tracker_info is not None,
|
||||
'is_tracker': is_tracker,
|
||||
'tracker_type': tracker_type_v2,
|
||||
'tracker_name': tracker_name_v2,
|
||||
'tracker_confidence': tracker_confidence_v2,
|
||||
'risk_score': risk_score,
|
||||
'is_audio_capable': _is_audio_capable_ble(name, device_type),
|
||||
'signal_strength': signal_info['strength'],
|
||||
'signal_label': signal_info['label'],
|
||||
|
||||
Reference in New Issue
Block a user