NETMON ROOTS MONITOR. CONTROL. UNDERSTAND. BACK TO THE ROOTS.
DE EN

Sicherheits-Audit — Juni 2026 — Runde 2

Code-Security-Review
NetMon Roots v1.1.14

Zweites automatisiertes Multi-Agenten-Security-Review auf Basis von Claude Sonnet 4.6. Erstmalig einbezogen: das neue Radio-Modul (radio_controller.py, 5 531 Zeilen), chad_controller.py, fun_controller.py, ai_analysis_service.py, lang_service.py, network_helpers.py, neue UI-Tabs sowie alle seit Runde 1 refaktorierten Bereiche (82 Proxy-Methoden entfernt, Security-Monitoring-Controller gesplittet).

← Runde 1 (9 Kandidaten, 0 Findings)
PDF herunterladen Kandidaten Hardening

Keine kritischen Schwachstellen gefunden

Alle vier initial identifizierten Kandidaten wurden in einer zweiten unabhängigen Filterrunde mit Konfidenz < 8/10 bewertet und als False Positives ausgeschlossen. Besonders noteworthy: der Radio-Modul-Kandidat (K1, SSRF-Verdacht) wurde nach nochmaliger Prüfung des tatsächlichen Datenflusses widerlegt — _normalize_station_stream_url() mit ALLOWED_RADIO_STREAM_SCHEMES = {“http”, “https”, “rtsp”, “rtmp”} validiert jede URL bereits vor der Aufnahme ins Station-Dict. Der erweiterte Codestand enthält keine ausnutzbaren Sicherheitslücken mit echtem Angriffspfad.

Datum
28. Juni 2026
Analysierte Version
v1.1.14 — Runde 2
Geänderte / neue Dateien
100+
Neue / revidierte Module
25+
Kritische Findings
0
Bewertete Kandidaten
4
Konfidenz-Schwelle
8/10
Analysewerkzeug
Claude Sonnet 4.6

Umfang & Methodik

Die Analyse folgte demselben dreistufigen Prozess wie Runde 1, ergänzt um eine dritte manuelle Verifikationsrunde für den Radio-Kandidaten K1. Schwerpunkt: alle Module, die in Runde 1 noch nicht im Scope waren — insbesondere das komplette Radio-Modul (5 531 Zeilen, externe API-Anbindung, mpv-Subprocess, ffmpeg-Recording) sowie neu hinzugekommene Services und UI-Tabs. Zusätzlich wurden alle seit Runde 1 geänderten Dateien auf Sicherheitsregressionen geprüft.

Phase 1 — Reconnaissance

Lesen aller neuen und geänderten Module; Fokus auf externe API-Anbindungen, Subprocess-Aufrufe mit externen Daten, URL-Handling, Datei-Operationen mit Nutzereingabe, eval/exec, Deserialisierung.

Phase 2 — Kandidaten-Analyse

Datenflussketten von externen Quellen (API-Antworten, Nutzerdialogen) bis zu sensitiven Operationen nachverfolgt. Besonderes Augenmerk: URL-Schemata an mpv, ffmpeg, urllib.request und webbrowser.open().

Phase 3 — False-Positive-Filter

Jeder Kandidat in einem unabhängigen Agenten re-analysiert. Ausschluss: DoS, Single-User-Desktop ohne Fremd-Input, stdout/stderr=DEVNULL + Re-Encoding verhindert Exfil, Browser-Sandbox, bestehende Schema-Allowlist-Validierung.

Phase 4 — Manuelle Verifikation (K1)

Zusätzliche Nachprüfung des Radio-Kandidaten durch direktes Lesen der Funktionskette: normalize_station_entry()_normalize_station_stream_url()ALLOWED_RADIO_STREAM_SCHEMES. Kandidat widerlegt.

Neu analysierte Module (Runde 2)

Datei / Modul Fokus Ergebnis
netmon/features/radio_controller.py mpv-Subprocess, ffmpeg-Recording, radio-browser.info API, urllib.request ICY-Fetch; URL-Schema-Validierung via _normalize_station_stream_url() Kein Finding
netmon/features/chad_controller.py KI-Integration, getattr-Zugriffsmuster, Datei-Import Kein Finding
netmon/features/fun_controller.py Subprocess-Aufrufe, Paketprüfung Kein Finding
netmon/features/speedtest_controller.py Speedtest-Subprocess, Ergebnis-Parsing Kein Finding
netmon/features/dot_controller.py Dropin-Generierung, systemd-Konfiguration Kein Finding
netmon/features/security_audit_controller.py Lynis/rkhunter-Aufrufe, Startup-Guard-Baseline-Lesen Kein Finding
netmon/services/ai_analysis_service.py KI-Analyse-Pipeline, Datenübertragung Kein Finding
netmon/services/lang_service.py Lokalisierung, JSON-Ladevorgang Kein Finding
netmon/services/network_helpers.py Netzwerk-Hilfsfunktionen, IP-Parsing Kein Finding
netmon/core/coordinator.py Zentraler Koordinator, Modul-Init Kein Finding
netmon/core/state.py Globaler Zustand, Attributzugriff Kein Finding
netmon/ui/tabs/radio_tab.py Radio-UI, Benutzerinteraktion, Event-Handling Kein Finding
netmon/ui/tabs/cleanup_assistant_tab.py System-Cleanup-UI, Dateioperationen Kein Finding
netmon/ui/tabs/download_scan_tab.py Download-Scan, ClamAV-Integration Kein Finding
netmon/ui/tabs/fun_tab.py Fun-Modul-UI Kein Finding
netmon/ui/tabs/chad_settings_tab.py KI-Einstellungen, API-Key-Handling Kein Finding
scripts/refactor_safety.py AST-Analyse, Caller-Check, Read-Only-Tool Kein Finding
netmon/app.py (Refaktorierung) 82 Proxy-Methoden entfernt — Angriffsflächenreduktion Keine Regression

Bewertete Kandidaten (alle ausgeschlossen)

Vier Muster wurden im ersten Analysedurchgang identifiziert und in parallelen, unabhängigen Filter-Agenten sowie einer abschließenden manuellen Verifikation re-analysiert. Kein Kandidat überschritt die Konfidenz-Schwelle von 8/10.

K1 — Radio-URL an mpv / urllib.request — manuell widerlegt

Konfidenz 8/10 → FP Ausgeschlossen

Datei: netmon/features/radio_controller.py

Initiale Bewertung (Phase 2): Radio-Stations-URLs aus dem externen radio-browser.info-API gelangen ohne Schema-Validierung an mpv (Zeile 4835) und urllib.request.urlopen() (Zeile 3150). Erstes Filter-Ergebnis: Konfidenz 8/10 — bestätigt.

Manuelle Nachprüfung: Beim direkten Lesen der Aufrufkette wurde _normalize_station_stream_url() (Zeile 298–309) identifiziert, die bei der automatischen Analyse übersehen wurde:

ALLOWED_RADIO_STREAM_SCHEMES = {"http", "https", "rtsp", "rtmp"}  # Zeile 103

def _normalize_station_stream_url(value) -> str:          # Zeile 298
    parsed = urllib.parse.urlparse(url)
    scheme = str(parsed.scheme or "").strip().lower()
    if scheme not in ALLOWED_RADIO_STREAM_SCHEMES:
        return ""                                          # nicht erlaubte Schemata werden abgelehnt
    return url

def normalize_station_entry(entry, ...):                  # Zeile 312
    url = _normalize_station_stream_url(...)              # Zeile 317
    if not name or not url:
        return None                                        # Station wird verworfen

Jede URL durchläuft _normalize_station_stream_url() bevor sie ins Station-Dict übernommen wird. Stationen mit nicht-erlaubten Schemata (file://, lavfi://, etc.) werden als None verworfen und nie gespeichert. _fetch_icy_stream_title() erhält ausschließlich vorvalidierte URLs aus dem Station-Dict.

Widerlegung: Der Datenfluss enthält eine korrekte Schema-Allowlist-Validierung, die der erste Analyse-Agent nicht erkannt hatte. file://, lavfi:// und alle anderen nicht-erlaubten Schemata werden in _normalize_station_stream_url() abgelehnt — bevor die URL mpv oder urllib.request erreicht. Kein SSRF-Pfad, kein Angriffspfad. False Positive.

K2 — webbrowser.open mit nicht validierter API-URL

Konfidenz 3/10 Ausgeschlossen

Datei: netmon/features/radio_controller.py, Zeile 5197

webbrowser.open(url, new=2) wird mit dem homepage-Feld aus der API-Antwort ohne Schema-Validierung aufgerufen. Auf Linux ruft webbrowser.open() intern xdg-open auf. Theoretisch könnte eine file://-URL übergeben werden.

Filterentscheid: Moderne Browser erzwingen strikte Same-Origin-Policy für file://-URLs. Eine geöffnete lokale Datei wird im eigenen Browser des Nutzers angezeigt — keine Exfiltration möglich. javascript:-URIs werden als Top-Level-URL nicht ausgeführt. Kein exploitierbarer Angriffspfad. Konfidenz 3/10 → ausgeschlossen.

K3 — ffmpeg -i mit nicht validierter API-URL

Konfidenz FP Ausgeschlossen

Datei: netmon/features/radio_controller.py, Zeile 2160

_recording_command(stream_url, output_path) übergibt die Station-URL als ffmpeg -i <url>-Argument. ffmpeg unterstützt Protokolle wie file://, concat://, lavfi:// u. a.

Filterentscheid: (1) Der URL-Wert stammt aus dem Station-Dict und wurde bereits durch _normalize_station_stream_url() gegen ALLOWED_RADIO_STREAM_SCHEMES validiert. (2) Selbst ohne diese Prüfung: stdin, stdout und stderr sind nach subprocess.DEVNULL umgeleitet; die Ausgabe wird durch den libmp3lame-Codec trancodiert. Kein Exfiltrationspfad.

K4 — Dateilese-Operation via Startup-Guard-Baseline

Konfidenz FP Ausgeschlossen

Datei: netmon/features/security_audit_controller.py, Zeilen 1173–1184

format_startup_guard_entry_details() öffnet und liest beliebige Dateipfade aus Startup-Guard-Einträgen, die aus einer nutzerschreibbaren JSON-Baseline-Datei stammen können.

Filterentscheid: Single-User-Desktop — kein Privilege-Boundary-Crossing. Die Baseline liegt im Konfig-Verzeichnis des aktuellen Nutzers. Ein Angreifer mit Zugriff auf die Baseline hat bereits volle Lesezugriff auf alle Dateien, die open() ohne sudo erreicht. Keine zusätzlichen Fähigkeiten erworben. Ausgeschlossen.

Sicherheitsverbesserungen seit Runde 1

Die folgenden Hardening-Empfehlungen aus Audit Runde 1 wurden im aktuellen Codestand umgesetzt.

🔒

ClamAV Tempdir: Symlink-Schutz implementiert — clamav_controller.py

Runde 1 empfahl, os.makedirs(exist_ok=True) durch eine Sequenz zu ersetzen, die Symlinks vor dem Anlegen des Verzeichnisses prüft und ablehnt (Punkt 4). Umgesetzt als _safe_makedirs_no_symlink(path) (Zeile 71): prüft via os.lstat(), ob der Zielpfad ein Symlink ist, und wirft bei positivem Befund einen RuntimeError. Empfehlung geschlossen.

URL-Schema-Validierung im Radio-Modul — radio_controller.py

Das Radio-Modul enthält bereits eine vollständige Schema-Allowlist-Validierung: ALLOWED_RADIO_STREAM_SCHEMES = {“http”, “https”, “rtsp”, “rtmp”} (Zeile 103), durchgesetzt durch _normalize_station_stream_url() (Zeile 298–309) via urllib.parse.urlparse(). Nicht-erlaubte Schemata werden vor der Speicherung im Station-Dict abgelehnt — mpv und urllib.request empfangen ausschließlich validierte URLs.

Angriffsflächenreduktion: 82 Proxy-Methoden aus app.py entfernt

Im Zuge der God-Object-Extraktion wurden 82 Proxy-Methoden aus app.py gelöscht, deren Controller-Gegenstücke in netmon/features/ bereits vorhanden waren. Alle Methoden wurden vorab per refactor_safety.py auf Null-Aufrufer verifiziert (AST-Check + grep). Commit 920cfc9b.

Hardening-Empfehlungen (keine kritischen Bugs)

Die folgenden Punkte sind keine Sicherheitslücken, sondern Defense-in-Depth-Maßnahmen aus Runde 1, die noch offen sind.

  • 🔧 Git-Subcommand-Allowlist in agent/runner.py: Sobald LLM-Output in run_command() fließt, eine explizite Subcommand-Allowlist ergänzen (status, diff, log, show). Derzeit latentes Architektur-Risiko (Runde 1, Punkt 1).
  • 🔧 IP-Validierung für WireGuard-Endpoints: parse_vpn_endpoint() sollte den Host-Teil mit ipaddress.ip_address() validieren, bevor er in UFW-Kommandos eingebettet wird (Runde 1, Punkt 2).
  • 🔧 Pfadprüfung in image_to_data_url(): Optional: Dateipfad zusätzlich auf das Benutzer-Homeverzeichnis einschränken. Aktuell kein ausnutzbarer Angriffspfad vorhanden (Runde 1, Punkt 3).
  • 🔧 Schema-Validierung für homepage-URLs im Radio-Modul: webbrowser.open(station["homepage"]) validiert das Schema nicht. Obwohl kein direkter Exploit-Pfad besteht (Browser-Sandbox), wäre eine analoge Allowlist-Prüfung vor dem webbrowser.open()-Aufruf defensive Best Practice.
  • 🔧 Shell-Quoting in Repository-Guard-Snippets: URI- und Pfadwerte in get_repository_guard_quick_action_snippet() mit shlex.quote() maskieren (Runde 1, Punkt 5).
  • 🔧 os.path.realpath() im Roots-Baseline-Guard: _normalize_guard_path_pattern() sollte os.path.abspath durch os.path.realpath() ersetzen, um Symlinks vor dem fnmatch-Check aufzulösen (Runde 1, Punkt 6).

Geprüfte Sicherheitskategorien

Kategorie Geprüft Ergebnis
Command Injection (subprocess, shell=True) Ja Kein Finding
Path Traversal (Dateioperationen mit Nutzereingabe) Ja Kein Finding
Privilege Escalation (sudo-Nutzung, Argument-Injektion) Ja Kein Finding
Unsichere Deserialisierung (pickle, yaml.load) Ja Kein Finding
Eval/Exec mit Nutzereingabe Ja Kein Finding
Hardcoded Credentials / API-Keys Ja Kein Finding
Authentication Bypass / Privilege Escalation Ja Kein Finding
Sensitive Data Exposure (PII in Logs) Ja Kein Finding
Externe API-Aufrufe mit unkontrollierten Daten Ja Kein Finding
SSRF via urllib.request / externe URL-Weitergabe Ja Kein Finding
Kryptographische Schwachstellen Ja Kein Finding
Symlink-Angriffe auf privilegierte Dateioperationen Ja Kein Finding
Clipboard-Injection / Snippet-Generierung Ja Kein Finding
URL-Schema-Validierung an Media-Subprocess Ja Kein Finding

Auditor: Claude Sonnet 4.6 (Anthropic) — Automatisiertes Multi-Agenten-Sicherheits-Review + manuelle Verifikation
Projektverantwortlicher: Sven Fröhlich
Datum: 28. Juni 2026
Analysierter Codestand: e334324a … 920cfc9b + Arbeitsstand (unstaged), gesamt 100+ Dateien — Runde 2
Methode: Statische Code-Analyse + manuelle Datenfluss-Verifikation — kein Laufzeit-Penetrationstest
Haftungsausschluss: Dieses Audit ersetzt keinen professionellen Penetrationstest durch eine zertifizierte Sicherheitsfirma. Die Analyse beschränkt sich auf den angegebenen Codestand. Nicht erfasst werden: Laufzeitverhalten, abhängige Systembibliotheken, Netzwerkkonfiguration und soziale Angriffsvektoren.

Zur Downloadseite   •   Aktuelles   •   Dokumentation   •   Legal / Lizenz