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

106 lines
7.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:
```bash
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:
```bash
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:
```bash
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
- [[Server Aingrad - Komplette Übersicht]] — Dienst-Tabelle und Neustart-Befehle oben korrigieren
- [[Melo App - Status]] — Stand dort ist v2.53.1, aktuell ist v2.56.2 + Fix-Branch