Files
hermes-vault/Notizen/Audit 14.08.2026 - Sicherheit & Code-Review.md
2026-08-17 10:56:15 +02:00

7.0 KiB
Raw Permalink Blame History

Audit 14.08.2026 Sicherheit & Code-Review

Stand: 14.08.2026 Umfang: Server Aingrad (Sicherheit + Aufräumen) und Melo App (Code-Review) Alle Änderungen live verifiziert · Backups: /home/dustin/backup-audit-2026-08-14/


⚠️ Zuerst: Zwei Korrekturen an bestehenden Notizen

1. Die Neustart-Befehle in Server Aingrad - Komplette Übersicht sind gefährlich. Dort steht noch:

sudo pkill -f baka_auth.py && python3 /home/dustin/scripts/baka_auth.py 8994 &

Die drei Dienste laufen inzwischen als systemd-Units mit Restart=always. Der Befehl killt den verwalteten Prozess, systemd startet ihn sofort neu und belegt den Port — der manuell gestartete Prozess scheitert dann an Address already in use, oder er gewinnt das Rennen und läuft unverwaltet weiter, bis die Shell endet. Richtig ist:

sudo systemctl restart baka-auth    # Port 8994
sudo systemctl restart melo-cloud   # Port 8993
sudo systemctl restart yt-proxy     # Port 8992
sudo systemctl status  baka-auth    # Zustand prüfen

2. Die Dienst-Tabelle ist beim Zugriff überholt. search.baka-net.de steht dort als „Offen" — seit heute Basic Auth. Ebenfalls nicht erfasst: matrix, element, admin-matrix, livekit, workspace, crash, ladder.


🔒 Behobene Sicherheitslücken

Befund Fix Verifiziert
/whoami Auth-Bypass: Basic-Header wurde ohne Passwortprüfung geglaubt → jeder bekam is_admin: true Caddy prüft das Passwort vor dem Proxy 401 statt 200
/api/cloud/yt-finder vor der Auth-Prüfung → jeder Request startet 120-s-Subprozess Doppelte Route entfernt 401 sofort
ladder offener Paywall-Proxy (Abuse auf eigene IP) Basic Auth 401
search offene SearXNG Basic Auth 401
admin-matrix Synapse-Panel offen Basic Auth 401
Navidrome-Admin-Passwort im Klartext in baka_auth.py /etc/baka-auth/navidrome_pw (640 root:dustin) Sync getestet
handle_profile listete bei Fehler alle Benutzernamen Meldung neutralisiert
Share-Codes aus random (vorhersagbar) secrets.choice, 6 → 8 Zeichen alte Codes gültig
baka_auth single-threaded → Logins serialisiert hinter Navidrome-Timeouts ThreadingWSGIServer + threading.Lock fürs Rate-Limit Login getestet

Caddy nutzt jetzt ein Snippet (baka_users) — Benutzerliste steht an einer Stelle statt viermal dupliziert.


🛑 Wichtigster Fund: Prod-Build von workspace umgeht die Auth

hermes-workspace läuft absichtlich mit pnpm dev. Der naheliegende „Fix" (Produktions-Build) wurde getestet — auf separatem Port 3021, ohne den laufenden Dienst anzufassen:

Route Dev (3020) Prod (3021)
/api/sessions {"ok":false,"error":"Unauthorized"} 200 + echte Chat-Titel, Previews, Token-Zahlen
/api/files 401 200

Der Produktions-Build setzt die Authentifizierung nicht durch. Eine Umstellung hätte sämtliche Agent-Konversationen öffentlich gemacht. Nicht auf node server-entry.js umstellen, bevor die Auth-Middleware im SSR-Pfad repariert ist. Prüfkommando danach:

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:PORT/api/sessions   # muss 401 sein

Verbleibender Nachteil des Dev-Servers: er liefert serverseitigen Quellcode aus (/src/server/auth-middleware.ts, /vite.config.ts → 200). Keine Secrets betroffen.env und /@fs/-Zugriffe sind mit Vite 7.3.5 korrekt geblockt (403), im ausgelieferten Code stehen nur Variablennamen.


🎵 Melo App & Cloud

Upload-Datenverlust behoben. upload() verknüpfte bei >85 % Titel-Ähnlichkeit auf einen bestehenden Song und verwarf die hochgeladene Datei — Live-Versionen und Remixes wurden durch das Studio-Original ersetzt. Entfernt. Begründung durch Messung: 323 von 325 Songs haben einen gültigen Fingerprint (99,4 %), fpcalc läuft. Greift der Fingerprint nicht, ist das Audio nachweislich anders; ein Dateiname darf das nicht überstimmen.

End-to-End getestet (zwei verschiedene Audios, 94 % ähnliche Namen): neu → new, identisch → linked (SHA256-Dedup intakt), anderes Audio → new mit eigener ID. Gespeicherte Dateien byte-identisch mit den Originalen. Testdaten restlos entfernt (wieder 325 Songs, 0 verwaiste Einträge).

cgi-Modul ersetzt. Multipart-Parsing läuft jetzt über die stdlib (email); cgi ist seit Python 3.13 entfernt (PEP 594) — der Upload wäre beim Distro-Upgrade wortlos ausgefallen. Gegen cgi.FieldStorage byte-identisch getestet (Nullbytes, CRLF, Boundary-Sequenzen, Umlaute).

deletePlaylist repariert. Schickte POST auf /api/v1/cloud/playlists; der Server unterscheidet dort nach Methode (POST = anlegen, DELETE = löschen). Das Löschen landete im Anlegen-Handler, scheiterte an der Namensprüfung und lieferte HTTP 200 mit status: error — die UI meldete trotzdem Erfolg, die Playlist blieb. Jetzt DELETE, Rückgabewert wird ausgewertet, 3 Regressionstests.

  • 202 Tests grün (vorher 199), flutter analyze ohne Befund
  • Commit 2223813 auf Branch fix/cloud-playlist-delete, noch nicht auf main
  • main hat zusätzlich v2.56.2 ungepusht

🧹 Aufgeräumt (~5 GB, 179 G → 184 G frei)

APT-Cache (1,1 G) · Build-Output des veralteten Duplikats git/melo_app (3,0 G) · npm-Cache · gateway-restart.log (29 M → 428 K) · drei leere Alt-Datenbanken in /var/lib/melo-cloud/.

Nicht angefasst: .gradle/caches (5,2 G) und .hermes/profiles/server-security/home (9,3 G — zweites Home mit eigenem Flutter, Chrome, Claude-Versionen). Beides regenerierbar, aber teuer bzw. potenziell in Benutzung.


📌 Offene Themen

  • /home/dustin/scripts ist kein Git-Repo. ~3400 Zeilen Python tragen Auth und Musik-Cloud, völlig unversioniert. Einziger Schutz sind die Backups von heute. Eigenes Repo dringend empfohlen (.gitignore für __pycache__ und Secrets).
  • Auth-Middleware im SSR-Pfad von workspace — Blocker für jeden Prod-Build.
  • Versionsstrings der App widersprechen sich: main.dart:32 → 2.56.1, settings_screen.dart:364 → 2.56.1, settings_screen.dart:500 → 2.56.0, home_screen.dart:1236 → 2.56.0. Nirgends 2.56.2. Besser eine Konstante, auf die alle vier zeigen.
  • Passwortloses sudo bleibt bewusst. backup_and_cleanup.sh läuft per Cron täglich 04:00 und braucht es — global entfernen bricht das Backup still. Falls Härtung: NOPASSWD auf die konkret nötigen Befehle einschränken und den Cron-Lauf testen.
  • _download/_stream in melo_cloud.py lesen ganze Dateien in den RAM (fh.read()), ebenso download() in der App (r.bodyBytes). Bei 50-MB-Songs und 7,7 GB RAM perspektivisch ein Thema.
  • Basic-Auth-Passwörter (baka, dustin, tinker) schützen jetzt deutlich mehr als vorher — falls eins schwach ist, wäre das der nächste Schritt.

Verwandte Notizen