Sicherheits-Audit — Juli 2026 — Runde 8
Code-Security-Review
NetMon Roots v1.1.18
Achtes automatisiertes Security-Review auf Basis von
Claude Fable 5. Schwerpunkt dieser Runde: das komplette
Secure-Browser-Subsystem
(manager.py, service.py, ui.py,
browser_container_builder.py) inklusive der neuen
Kindersicherung, die fünf neuen
Linux-Hilfe-Services
(linux_help_*_service.py, u. a. PDF-Erzeugung), die
Controller für Radio, Speedtest, VPN und Paketmitschnitt sowie die
Website-Endpunkte (download.php,
download-stats.php). Ergebnis: keine ausnutzbaren
Schwachstellen. Zwei Kandidaten wurden von dedizierten
Validierungs-Sub-Agenten geprüft — die
Same-User-Umgehbarkeit der Kindersicherung wurde dabei als
bewusste Design-Entscheidung eingestuft und
dokumentiert, der Favicon-/Logo-Download als False Positive verworfen.
Eine daraus abgeleitete Defense-in-Depth-Härtung
(http/https-Allowlist für Radio-Logo-Downloads) wurde direkt
umgesetzt und mit einem Regressionstest abgesichert. Alle
Runde-7-Härtungen sind unverändert intakt.
Umfang & Methodik
Geprüft wurde der vollständige Branch-Diff
(feature/secure-browser-manager, Codestand
c2087b63 plus Arbeitsstand) mit Schwerpunkt auf den in
Runde 7 nicht fokussierten Bereichen: das
Secure-Browser-Subsystem (manager.py,
service.py, ui.py,
secure_browser_tab.py,
browser_container_builder.py) inklusive Kindersicherung
(create_child_lock_payload(),
browser_lock.py, child-lock.json), die
fünf neuen Linux-Hilfe-Services
(linux_help_document/library/pdf/prompt/viewer_service.py),
die Controller packet_capture_controller.py,
speedtest_controller.py, vpn_controller.py,
das Radio-Modul (netmon_radio_app.py,
netmon_radio_core.py), die Website-Endpunkte
(download.php, download-stats.php,
download-config.php, app.js) und die
Build-Skripte. Die in Runde 7 gehärteten RKHunter-/ClamAV-
Pfade wurden auf Regressionen gegengeprüft.
Phase 1 — Diff- & Reconnaissance
Vollständiger git diff des Branches
(3,7 MB) plus Sichtung der unversionierten neuen Services.
Abgleich mit den etablierten Sicherheitsmustern des Projekts
(run_cmd() in Listenform,
_normalize_allowed_path(),
_safe_makedirs_no_symlink()).
Phase 2 — Kandidaten-Analyse
Ein dedizierter Analyse-Sub-Agent verfolgte Datenflussketten von
Fremdeingaben (besuchte Websites, API-Antworten von
radio-browser.info, Dateinamen, Containernamen) bis zu sensiblen
Operationen (subprocess, urlopen,
Dateisystem-Schreibpfade, .desktop-Generierung).
2 Kandidaten identifiziert.
Phase 3 — False-Positive-Validierung
Für jeden Kandidaten lief ein eigener Validierungs-Sub-Agent mit striktem FP-Filter und Konfidenz-Scoring. Ergebnis: Kindersicherung = By-Design-Limitierung (1/10), Favicon-/Logo-Fetch = False Positive (1/10) — beide weit unter der Schwelle von 8/10.
Phase 4 — Härtung & Regressionscheck
Die aus K2 abgeleitete Konsistenz-Härtung (http/https-Allowlist im Radio-Logo-Download) wurde umgesetzt und mit einem neuen Regressionstest abgesichert. Suiten ausgeführt: Secure-Browser-Modul & Container-Builder (173), RKHunter/ClamAV/ Linux-Hilfe (80), Radio-Modul (121) — alle sicherheitsrelevanten Tests grün.
Sicherheitsfokus (Runde 8)
| Datei / Modul | Fokus | Ergebnis |
|---|---|---|
browser_container_builder.py — Kindersicherung
(build_browser_lock_helper(), start.sh-Gate) |
Passwort-Gate vor dem Browserstart: Krypto, Fail-Closed-Verhalten, Umgehbarkeit im selben Linux-Konto | Bewusste Entscheidung |
browser_container_builder.py —
fetch_url() / resolve_favicon_download() |
Favicon-Download von fremden Websites: file://-Lesezugriff,
SSRF, Pfadeinfluss aus Fremddaten |
Kein Finding (Allowlist vorhanden) |
netmon_radio_app.py — _download_station_logo() |
Logo-URLs aus der radio-browser.info-API gingen ohne
Schema-Prüfung an urlopen |
K2 → gehärtet |
manager.py / service.py — Containernamen,
Builder-Aufrufe |
Command-/Argument-Injection, Pfad-Traversal über Containernamen | Kein Finding (Regex-Validierung, list-form) |
linux_help_*_service.py (5 neue Services) |
PDF-Erzeugung (Escaping), Dokument-Import/-Löschung (Zielpfade), Prompt-Aufbau | Kein Finding |
download.php / download-stats.php |
Pfad-Traversal über id-Parameter, Stored XSS in
Statistikfeldern |
Kein Finding (Fix-Map, htmlspecialchars) |
| Runde-7-Bereiche (propupd-Gate, ClamAV-DB, rkhunter-Pfade, Scan-Worker) | Regression der Härtungen? | Weiterhin intakt |
Bedrohungsmodell wie in den Vorrunden: NetMon ist ein Einzelnutzer-Desktop-Werkzeug. Relevante Angreifer sind Fremdinhalte (besuchte Websites, API-Antworten, Dateinamen), andere lokale Nutzer auf einem geteilten Host und manipulierte Eingabedateien — nicht der Nutzer selbst im eigenen Konto. Das Audit ersetzt keinen Laufzeit-Penetrationstest.
Bewertete Kandidaten
Zwei Kandidaten wurden identifiziert und jeweils von einem eigenen Validierungs-Sub-Agenten gegengeprüft. Beide erhielten Konfidenz 1/10 — weit unter der Schwelle von 8/10 für ein bestätigtes, ausnutzbares Finding. K1 wird als bewusste Design-Entscheidung dokumentiert, K2 führte zu einer Konsistenz-Härtung.
K1 — Kindersicherung: Same-User-Umgehbarkeit
Konfidenz 1/10 Bewusste Design-EntscheidungDateien:
netmon/modules/secure_browser/manager.py
(create_child_lock_payload()),
tools/secure_browser_manager/browser_container_builder.py
(start.sh-Gate, build_browser_lock_helper()),
netmon/modules/secure_browser/ui.py (Tab-Integration).
Die Kindersicherung im Secure-Browser-Tab schützt den Start
eines Browser-Containers mit einem Passwort. Die Umsetzung ist
kryptographisch korrekt: PBKDF2-SHA256 mit
200.000 Iterationen und zufälligem
16-Byte-Salt, Ablage als Hash in child-lock.json
(Rechte 0600), Prüfung vor jedem Start über
browser_lock.py mit konstantzeitigem Vergleich
(hmac.compare_digest), maximal drei Versuchen und
Fail-Closed-Verhalten (|| exit 1 in beiden
start.sh-Varianten; fehlende oder defekte
Lock-Datei blockiert den Start).
Geprüfte Frage: Ein Nutzer im
selben Linux-Konto kann das Gate umgehen — etwa durch
direkten Start von ./firefox/firefox --no-remote --profile
./profile, Löschen der nutzereigenen
child-lock.json oder Editieren von
start.sh. Ist das eine Schwachstelle?
Einordnung des Validierungs-Sub-Agenten: Nein. „Angreifer“ und „Opfer“ teilen dieselbe Linux-UID — es existiert keine vom Betriebssystem durchsetzbare Vertrauensgrenze. Diese Umgehbarkeit ist eine inhärente Kategorie-Eigenschaft jeder Same-Account-Kindersicherung, kein Implementierungsfehler: Dem Kind gehören Firefox-Kopie, Profil und Lock-Datei, und es könnte ebenso jeden anderen Browser des Systems starten. Jede „Härtung“ innerhalb desselben Kontos wäre Sicherheitstheater; eine echte Durchsetzung ergäbe nur mit getrennten Betriebssystem-Konten oder Root-Rechten — was dem bewussten No-Root-Design des Secure-Browser-Moduls widerspräche.
K2 — Favicon-/Logo-Download: file://-Lesezugriff & SSRF
Konfidenz 1/10
False Positive — Konsistenz gehärtet
Dateien:
tools/secure_browser_manager/browser_container_builder.py
(fetch_url(), resolve_favicon_download()),
netmon/netmon_radio_app.py
(_download_station_logo()).
Beim Anlegen eines Browser-Containers lädt NetMon das Favicon
der eingetragenen Startseite; die Icon-URL stammt dabei aus dem
HTML der fremden Website (<link rel="icon">,
via urljoin aufgelöst). Eine bösartige Website
könnte href="file:///etc/passwd" liefern.
Bewertung: fetch_url() erzwingt vor
jedem urlopen eine http/https-Allowlist — mit
Kommentar, der genau dieses Szenario benennt — und deckt damit
alle Aufrufer ab. Die geladenen Bytes werden ausschließlich
unter festem Namen (favicon.png/.ico/.svg, Endung per
Magic-Byte-Erkennung) im Container-Verzeichnis gespeichert; weder
URL noch Content-Disposition beeinflussen den Pfad. Umleitungen
von http(s) auf file:// verhindert bereits
urllib selbst.
Einziger Nebenbefund: Der Radio-Logo-Download
(_download_station_logo()) übergab die
Favicon-URL aus der radio-browser.info-API als einziger Fetcher
ohne Schema-Prüfung an urlopen. Auch das
ist nicht ausnutzbar (Zielpfad ist ein fester SHA-256-Hashname im
nutzereigenen Cache, PIL re-encodiert nach PNG, kein
Rückkanal zum Angreifer) — aber inkonsistent zum
Builder-Standard.
_station_logo_url() begrenzt Logo-URLs jetzt wie
fetch_url() auf http/https;
alles andere (file://, ftp://,
data:, javascript:, schemalose URLs) wird
verworfen, bevor ein Download-Thread startet. Mit neuem
Regressionstest abgesichert
(test_station_logo_url_allows_only_web_schemes).
Umgesetzte Härtungsmaßnahmen (Runde 8)
Auch ohne bestätigtes ausnutzbares Finding wurde die aus K2 abgeleitete Konsistenzlücke direkt geschlossen — fail-closed und mit Regressionstest.
http/https-Allowlist für Radio-Logo-Downloads — netmon_radio_app.py
_station_logo_url() akzeptiert nur noch
http-/https-URLs aus der
radio-browser.info-API — dieselbe Regel, die
fetch_url() im Container-Builder bereits erzwingt.
Nicht-Web-Schemata erreichen urlopen damit in keinem
Codepfad des Projekts mehr.
Neuer Regressionstest — Radio-Suite
test_station_logo_url_allows_only_web_schemes stellt
sicher, dass file://, ftp://,
data:, javascript: und schemalose URLs
dauerhaft verworfen werden. Sicherheitsrelevante Suiten nach der
Härtung: Secure-Browser-Modul & Container-Builder
(173 Tests), RKHunter/ClamAV/Linux-Hilfe (80 Tests),
Radio-Modul (121 Tests) — alle sicherheitsrelevanten
Tests grün. (Zwei vorbestehende, umgebungsabhängige
Desktop-Launch-Tests der Radio-Suite schlagen auf dem
Audit-Host unabhängig vom Codestand fehl und haben keinen
Sicherheitsbezug.)
Geprüfte Sicherheitskategorien
| Kategorie | Geprüft | Ergebnis |
|---|---|---|
Command Injection (subprocess, shell=True) |
Ja | Kein Finding (durchgängig list-form) |
| Pfad-Traversal (Containernamen, Icon-/Logo-Speicherpfade, Hilfe-Dokumente) | Ja | Kein Finding (Regex-Validierung, feste Namen) |
Lokaler Dateizugriff / SSRF über Fremd-URLs
(file://, interne Hosts) |
Ja | K2 → gehärtet (http/https-Allowlist) |
| Autorisierung / Zugriffskontrolle (Kindersicherung) | Ja | K1 → bewusste Design-Entscheidung |
| Kryptographie (Passwort-Hashing der Kindersicherung) | Ja | Kein Finding (PBKDF2-SHA256, Salt, compare_digest) |
.desktop-/Launcher-Injection (Exec-/Icon-Felder) |
Ja | Kein Finding (validierte Namen, CR/LF-Strip) |
XSS / Pfad-Traversal in Website-PHP
(download.php, download-stats.php) |
Ja | Kein Finding (Fix-Map, htmlspecialchars) |
| Unsichere Deserialisierung (pickle, yaml.load, eval, exec) | Ja | Kein Finding |
PDF-Injection in der Linux-Hilfe
(render_text_pdf) |
Ja | Kein Finding (Text-Escaping) |
| Hardcoded Credentials / API-Keys | Ja | Kein Finding |
| Regression der Runde-7-Härtungen (propupd-Gate, ClamAV-DB-Prüfung, rkhunter-Pfad-Allowlist, Scan-Worker) | Ja | Alle intakt |
Auditor: Claude Fable 5 (Anthropic) —
Analyse-Sub-Agent + zwei dedizierte False-Positive-Validierungs-Sub-Agenten
Projektverantwortlicher: Sven Fröhlich
Datum: 18. Juli 2026
Analysierter Codestand:
c2087b63 + Arbeitsstand (modified/untracked), Fokus
Secure-Browser-Subsystem inkl. Kindersicherung, Linux-Hilfe-Services,
Medien-Controller & Website-PHP — Runde 8
Methode: Statische Code-Analyse + manuelle
Datenfluss-Verifikation + Konfidenz-gescorte FP-Validierung pro
Kandidat + Umsetzung einer Defense-in-Depth-Härtung mit
Regressionstest + Regressions-Gegenprüfung der
Runde-7-Härtungen (Testsuiten: 173 + 80 + 121 Tests, alle
sicherheitsrelevanten Tests bestanden) — 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.