Add root privilege check and warning display

- Add startup check in app.py for root/sudo privileges
- Show warning in terminal if not running as root
- Add running_as_root flag to TSCM devices API response
- Display privilege warning in TSCM UI when not running as root
- Show command to run with sudo in the warning
- Add CSS styling for privilege warning banner

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Smittix
2026-01-14 15:37:56 +00:00
parent ff7c768287
commit db2f46b46e
3 changed files with 83 additions and 1 deletions

22
app.py
View File

@@ -548,6 +548,28 @@ def main() -> None:
print("=" * 50)
print()
# Check if running as root (required for WiFi monitor mode, some BT operations)
import os
if os.geteuid() != 0:
print("\033[93m" + "=" * 50)
print(" ⚠️ WARNING: Not running as root/sudo")
print("=" * 50)
print(" Some features require root privileges:")
print(" - WiFi monitor mode and scanning")
print(" - Bluetooth low-level operations")
print(" - RTL-SDR access (on some systems)")
print()
print(" To run with full capabilities:")
print(" sudo -E venv/bin/python intercept.py")
print("=" * 50 + "\033[0m")
print()
# Store for API access
app.config['RUNNING_AS_ROOT'] = False
else:
app.config['RUNNING_AS_ROOT'] = True
print("Running as root - full capabilities enabled")
print()
# Clean up any stale processes from previous runs
cleanup_stale_processes()

View File

@@ -596,7 +596,25 @@ def get_tscm_devices():
except Exception as e:
logger.warning(f"Error detecting SDR devices: {e}")
return jsonify({'status': 'success', 'devices': devices})
# Check if running as root
import os
from flask import current_app
running_as_root = current_app.config.get('RUNNING_AS_ROOT', os.geteuid() == 0)
warnings = []
if not running_as_root:
warnings.append({
'type': 'privileges',
'message': 'Not running as root. WiFi monitor mode and some Bluetooth features require sudo.',
'action': 'Run with: sudo -E venv/bin/python intercept.py'
})
return jsonify({
'status': 'success',
'devices': devices,
'running_as_root': running_as_root,
'warnings': warnings
})
def _scan_wifi_networks(interface: str) -> list[dict]:

View File

@@ -2075,6 +2075,31 @@
.tscm-status-message .status-icon {
font-size: 16px;
}
.tscm-privilege-warning {
padding: 10px 12px;
background: rgba(255, 51, 51, 0.15);
border: 1px solid rgba(255, 51, 51, 0.4);
border-radius: 6px;
color: var(--text-primary);
font-size: 11px;
display: flex;
align-items: flex-start;
gap: 10px;
margin-bottom: 12px;
}
.tscm-privilege-warning .warning-icon {
font-size: 18px;
flex-shrink: 0;
}
.tscm-privilege-warning .warning-action {
margin-top: 4px;
font-family: 'JetBrains Mono', monospace;
font-size: 10px;
color: var(--accent-cyan);
background: rgba(0, 0, 0, 0.3);
padding: 4px 8px;
border-radius: 3px;
}
.tscm-device-reasons {
font-size: 10px;
color: var(--text-secondary);
@@ -10125,6 +10150,23 @@
sdrSelect.innerHTML = '<option value="">No SDR devices found</option>';
}
// Show warnings (e.g., not running as root)
const warningsDiv = document.getElementById('tscmDeviceWarnings');
if (data.warnings && data.warnings.length > 0) {
warningsDiv.innerHTML = data.warnings.map(w =>
`<div class="tscm-privilege-warning">
<span class="warning-icon">⚠️</span>
<div>
<strong>${escapeHtml(w.message)}</strong>
${w.action ? `<div class="warning-action">${escapeHtml(w.action)}</div>` : ''}
</div>
</div>`
).join('');
warningsDiv.style.display = 'block';
} else {
warningsDiv.style.display = 'none';
}
} catch (e) {
console.error('Failed to refresh TSCM devices:', e);
}