mirror of
https://github.com/smittix/intercept.git
synced 2026-07-21 15:58:10 -07:00
Fix capabilities display and add 'Add to Known Devices' button
- Fix tscmShowCapabilities to parse nested API response structure - Build can/cannot detect lists dynamically from actual capabilities - Display system info, limitations, and disclaimer - Add 'Add to Known Devices' button in device detail modal - New tscmAddToKnownDevices function with custom name prompt Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
+127
-27
@@ -8547,27 +8547,40 @@
|
|||||||
}
|
}
|
||||||
html += `</table></div>`;
|
html += `</table></div>`;
|
||||||
|
|
||||||
|
// Actions section - always show with "Add to Known Devices"
|
||||||
|
const deviceIdentifier = device.bssid || device.mac || (device.frequency ? device.frequency.toString() : id);
|
||||||
|
const deviceName = device.name || device.ssid || device.essid || (device.frequency ? device.frequency + ' MHz' : 'Unknown');
|
||||||
|
html += `
|
||||||
|
<div class="device-detail-section">
|
||||||
|
<h4>Actions</h4>
|
||||||
|
<div style="display: flex; gap: 8px; flex-wrap: wrap;">
|
||||||
|
`;
|
||||||
|
|
||||||
// Add "Listen" button for RF signals
|
// Add "Listen" button for RF signals
|
||||||
if (protocol === 'rf' && device.frequency) {
|
if (protocol === 'rf' && device.frequency) {
|
||||||
const freq = device.frequency;
|
const freq = device.frequency;
|
||||||
html += `
|
html += `
|
||||||
<div class="device-detail-section" style="border-bottom: none;">
|
<button class="tscm-action-btn" onclick="listenToRfSignal(${freq}, 'fm')">
|
||||||
<h4>Actions</h4>
|
🎧 Listen (FM)
|
||||||
<div style="display: flex; gap: 8px; flex-wrap: wrap;">
|
</button>
|
||||||
<button class="tscm-action-btn" onclick="listenToRfSignal(${freq}, 'fm')">
|
<button class="tscm-action-btn" onclick="listenToRfSignal(${freq}, 'am')">
|
||||||
🎧 Listen (FM)
|
🎧 Listen (AM)
|
||||||
</button>
|
</button>
|
||||||
<button class="tscm-action-btn" onclick="listenToRfSignal(${freq}, 'am')">
|
|
||||||
🎧 Listen (AM)
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div style="font-size: 10px; color: var(--text-secondary); margin-top: 8px;">
|
|
||||||
Opens Listening Post and tunes to this frequency
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add "Add to Known Devices" button for all device types
|
||||||
|
html += `
|
||||||
|
<button class="tscm-action-btn" style="background: var(--accent-cyan);" onclick="tscmAddToKnownDevices('${escapeHtml(deviceIdentifier)}', '${escapeHtml(deviceName)}', '${protocol}')">
|
||||||
|
✅ Add to Known Devices
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div style="font-size: 10px; color: var(--text-secondary); margin-top: 8px;">
|
||||||
|
${protocol === 'rf' ? 'Listen buttons open Listening Post. ' : ''}Known devices are excluded from threat scoring in future sweeps.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
// Add indicators section
|
// Add indicators section
|
||||||
if (device.indicators && device.indicators.length > 0) {
|
if (device.indicators && device.indicators.length > 0) {
|
||||||
html += `
|
html += `
|
||||||
@@ -9097,48 +9110,104 @@
|
|||||||
|
|
||||||
if (data.status === 'success') {
|
if (data.status === 'success') {
|
||||||
const caps = data.capabilities;
|
const caps = data.capabilities;
|
||||||
|
|
||||||
|
// Determine availability from nested structure
|
||||||
|
const wifiAvailable = caps.wifi && caps.wifi.mode !== 'unavailable';
|
||||||
|
const btAvailable = caps.bluetooth && caps.bluetooth.mode !== 'unavailable';
|
||||||
|
const rfAvailable = caps.rf && caps.rf.available;
|
||||||
|
|
||||||
|
// Build can/cannot detect lists based on capabilities
|
||||||
|
const canDetect = [];
|
||||||
|
const cannotDetect = [];
|
||||||
|
|
||||||
|
if (wifiAvailable) {
|
||||||
|
canDetect.push('WiFi access points and networks');
|
||||||
|
canDetect.push('Hidden SSIDs (presence only)');
|
||||||
|
if (caps.wifi.monitor_capable) {
|
||||||
|
canDetect.push('WiFi client devices (probe requests)');
|
||||||
|
canDetect.push('Deauthentication attacks');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cannotDetect.push('WiFi networks - no adapter available');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (btAvailable) {
|
||||||
|
canDetect.push('Bluetooth Classic devices');
|
||||||
|
canDetect.push('BLE beacons and trackers');
|
||||||
|
canDetect.push('Audio-capable Bluetooth devices');
|
||||||
|
} else {
|
||||||
|
cannotDetect.push('Bluetooth devices - no adapter available');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rfAvailable) {
|
||||||
|
const minFreq = caps.rf.frequency_range_mhz?.min || 0;
|
||||||
|
const maxFreq = caps.rf.frequency_range_mhz?.max || 0;
|
||||||
|
canDetect.push(`RF signals (${minFreq}-${maxFreq} MHz)`);
|
||||||
|
canDetect.push('Unknown transmitters in frequency range');
|
||||||
|
} else {
|
||||||
|
cannotDetect.push('RF signals - no SDR device available');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always cannot detect
|
||||||
|
cannotDetect.push('Wired surveillance devices');
|
||||||
|
cannotDetect.push('Passive listening devices (no transmitter)');
|
||||||
|
cannotDetect.push('Devices that are powered off');
|
||||||
|
cannotDetect.push('Burst/store-and-forward transmitters (when idle)');
|
||||||
|
|
||||||
content.innerHTML = `
|
content.innerHTML = `
|
||||||
<div class="device-detail-header classification-cyan">
|
<div class="device-detail-header classification-cyan">
|
||||||
<h3>Sweep Capabilities</h3>
|
<h3>Sweep Capabilities</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="device-detail-section">
|
<div class="device-detail-section">
|
||||||
|
<h4>System Information</h4>
|
||||||
|
<div style="font-size: 11px; color: var(--text-muted); margin-bottom: 12px;">
|
||||||
|
OS: ${escapeHtml(caps.system?.os || 'Unknown')} ${escapeHtml(caps.system?.os_version || '')} |
|
||||||
|
Root: ${caps.system?.is_root ? 'Yes' : 'No'}
|
||||||
|
</div>
|
||||||
<h4>Available Detection Methods</h4>
|
<h4>Available Detection Methods</h4>
|
||||||
<div class="capabilities-grid">
|
<div class="capabilities-grid">
|
||||||
<div class="cap-detail-item ${caps.wifi_available ? 'available' : 'unavailable'}">
|
<div class="cap-detail-item ${wifiAvailable ? 'available' : 'unavailable'}">
|
||||||
<span class="cap-icon">📶</span>
|
<span class="cap-icon">📶</span>
|
||||||
<span class="cap-name">WiFi Scanning</span>
|
<span class="cap-name">WiFi Scanning</span>
|
||||||
<span class="cap-status">${caps.wifi_available ? 'Available' : 'Not Available'}</span>
|
<span class="cap-status">${wifiAvailable ? caps.wifi.mode : 'Not Available'}</span>
|
||||||
${caps.wifi_interface ? `<span class="cap-detail">${caps.wifi_interface}</span>` : ''}
|
${caps.wifi?.interface ? `<span class="cap-detail">${escapeHtml(caps.wifi.interface)}</span>` : ''}
|
||||||
</div>
|
</div>
|
||||||
<div class="cap-detail-item ${caps.bluetooth_available ? 'available' : 'unavailable'}">
|
<div class="cap-detail-item ${btAvailable ? 'available' : 'unavailable'}">
|
||||||
<span class="cap-icon">🔵</span>
|
<span class="cap-icon">🔵</span>
|
||||||
<span class="cap-name">Bluetooth Scanning</span>
|
<span class="cap-name">Bluetooth Scanning</span>
|
||||||
<span class="cap-status">${caps.bluetooth_available ? 'Available' : 'Not Available'}</span>
|
<span class="cap-status">${btAvailable ? caps.bluetooth.mode : 'Not Available'}</span>
|
||||||
${caps.bt_adapter ? `<span class="cap-detail">${caps.bt_adapter}</span>` : ''}
|
${caps.bluetooth?.adapter ? `<span class="cap-detail">${escapeHtml(caps.bluetooth.adapter)}</span>` : ''}
|
||||||
</div>
|
</div>
|
||||||
<div class="cap-detail-item ${caps.sdr_available ? 'available' : 'unavailable'}">
|
<div class="cap-detail-item ${rfAvailable ? 'available' : 'unavailable'}">
|
||||||
<span class="cap-icon">📡</span>
|
<span class="cap-icon">📡</span>
|
||||||
<span class="cap-name">RF/SDR Scanning</span>
|
<span class="cap-name">RF/SDR Scanning</span>
|
||||||
<span class="cap-status">${caps.sdr_available ? 'Available' : 'Not Available'}</span>
|
<span class="cap-status">${rfAvailable ? 'Available' : 'Not Available'}</span>
|
||||||
${caps.sdr_device ? `<span class="cap-detail">${caps.sdr_device}</span>` : ''}
|
${caps.rf?.device_type ? `<span class="cap-detail">${escapeHtml(caps.rf.device_type)}</span>` : ''}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="device-detail-section">
|
<div class="device-detail-section">
|
||||||
<h4>What This Sweep CAN Detect</h4>
|
<h4>What This Sweep CAN Detect</h4>
|
||||||
<ul class="cap-can-list">
|
<ul class="cap-can-list">
|
||||||
${(caps.can_detect || []).map(item => `<li>✅ ${escapeHtml(item)}</li>`).join('')}
|
${canDetect.map(item => `<li>✅ ${escapeHtml(item)}</li>`).join('')}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="device-detail-section">
|
<div class="device-detail-section">
|
||||||
<h4>What This Sweep CANNOT Detect</h4>
|
<h4>What This Sweep CANNOT Detect</h4>
|
||||||
<ul class="cap-cannot-list">
|
<ul class="cap-cannot-list">
|
||||||
${(caps.cannot_detect || []).map(item => `<li>❌ ${escapeHtml(item)}</li>`).join('')}
|
${cannotDetect.map(item => `<li>❌ ${escapeHtml(item)}</li>`).join('')}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
${caps.all_limitations && caps.all_limitations.length > 0 ? `
|
||||||
|
<div class="device-detail-section">
|
||||||
|
<h4>Current Limitations</h4>
|
||||||
|
<ul class="cap-cannot-list">
|
||||||
|
${caps.all_limitations.map(item => `<li>⚠️ ${escapeHtml(item)}</li>`).join('')}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
` : ''}
|
||||||
<div class="device-detail-disclaimer">
|
<div class="device-detail-disclaimer">
|
||||||
<strong>Important:</strong> This tool detects wireless RF emissions only.
|
<strong>Important:</strong> ${escapeHtml(caps.disclaimer || 'This tool detects wireless RF emissions only. Professional TSCM requires physical inspection, NLJD, thermal imaging, and spectrum analysis equipment.')}
|
||||||
Professional TSCM requires physical inspection, NLJD, thermal imaging, and spectrum analysis equipment.
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
} else {
|
} else {
|
||||||
@@ -9249,6 +9318,37 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function tscmAddToKnownDevices(identifier, name, deviceType) {
|
||||||
|
// Ask for optional custom name
|
||||||
|
const customName = prompt(`Add "${name}" to known devices.\n\nEnter a friendly name (or leave blank to use default):`, name);
|
||||||
|
if (customName === null) return; // User cancelled
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('/tscm/known-devices', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
identifier: identifier,
|
||||||
|
name: customName || name,
|
||||||
|
device_type: deviceType
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
if (data.status === 'success') {
|
||||||
|
// Show success message
|
||||||
|
alert(`"${customName || name}" added to known devices.\n\nThis device will be excluded from threat scoring in future sweeps.`);
|
||||||
|
// Close the device modal
|
||||||
|
closeTscmDeviceModal();
|
||||||
|
} else {
|
||||||
|
alert(data.message || 'Failed to add device');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to add to known devices:', e);
|
||||||
|
alert('Failed to add device to known list');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Cases Management
|
// Cases Management
|
||||||
async function tscmShowCases() {
|
async function tscmShowCases() {
|
||||||
const modal = document.getElementById('tscmDeviceModal');
|
const modal = document.getElementById('tscmDeviceModal');
|
||||||
|
|||||||
Reference in New Issue
Block a user