# STEP 4.4 – KLARTEXT-CREDENTIALS ENTFERNT (LÜCKE #28) # Status: ABGESCHLOSSEN --- ## Fundstellen | Datei | Problem | |-------|---------| | `aza_email_config.json` | Klartext-Passwort im `password`-Feld: `"password": "Asdfasdf22@@As96k324"` | Keine weiteren Klartext-Credentials in JSON/YAML/INI-Dateien gefunden. **Hinweis:** Das hier entfernte Passwort war ein echtes Produktivpasswort. Es sollte umgehend beim Mail-Provider geändert werden. --- ## Neue ENV-Variablen | Variable | Beschreibung | |----------|-------------| | `AZA_EMAIL_PASSWORD_0` | Passwort für das erste E-Mail-Konto | | `AZA_EMAIL_PASSWORD_1` | Passwort für das zweite E-Mail-Konto (falls vorhanden) | | `AZA_EMAIL_PASSWORD_N` | Passwort für das N-te Konto (0-basiert) | ### Setzen unter Windows: ```cmd set AZA_EMAIL_PASSWORD_0=MeinSicheresPasswort ``` ### Setzen unter Linux/Mac: ```bash export AZA_EMAIL_PASSWORD_0="MeinSicheresPasswort" ``` ### Dauerhaft (Windows PowerShell): ```powershell [Environment]::SetEnvironmentVariable("AZA_EMAIL_PASSWORD_0", "MeinPasswort", "User") ``` --- ## Geänderte Dateien | Datei | Änderung | |-------|----------| | `aza_email.py` | Neue Funktionen: `_get_account_password()`, `_strip_passwords()`, `_check_plaintext_migration()` | | `aza_email.py` | `load_email_config()`: Lädt Passwörter aus ENV, ignoriert Klartext in JSON, gibt Warnung | | `aza_email.py` | `save_email_config()`: Strippt `password` und `_password` vor dem Schreiben | | `aza_email.py` | Alle IMAP/SMTP-Stellen: `acc.get("password")` → `acc.get("_password")` | | `aza_email.py` | Account-Dialog: Passwort wird als `_password` (RAM-only) gespeichert | | `aza_email_config.json` | Klartext-Passwort entfernt | --- ## Architektur ### Passwort-Fluss (NEU): ``` ENV (AZA_EMAIL_PASSWORD_0) │ ▼ load_email_config() ──► acc["_password"] (nur RAM) │ ▼ IMAP/SMTP Login ──► acc.get("_password", "") │ ▼ save_email_config() ──► _strip_passwords() ──► JSON OHNE Passwort ``` ### Passwort-Fluss (GUI-Eingabe): ``` Account-Dialog (Passwort-Feld) │ ▼ save_account() ──► acc["_password"] = pw_input (nur RAM) │ ▼ _save_config() ──► save_email_config() ──► _strip_passwords() ──► JSON OHNE Passwort ``` Das `_password`-Feld existiert NUR im RAM. Es wird NIE in JSON geschrieben. Das `password`-Feld wird beim Laden aus JSON ignoriert und beim Speichern entfernt. --- ## Migrationsverhalten Wenn `aza_email_config.json` noch ein `password`-Feld enthält: 1. **Warnung auf stderr:** ``` SICHERHEITSWARNUNG: Klartext-Passwoerter in aza_email_config.json gefunden! Betroffene Konten: andre.surovy@haut-winterthur.ch Bitte entfernen und stattdessen ENV-Variablen setzen: AZA_EMAIL_PASSWORD_0 Die Passwoerter in der Datei werden IGNORIERT. ``` 2. **Klartext-Passwort wird NICHT übernommen** (kein Auto-Migrate) 3. **Benutzer muss ENV-Variable setzen**, damit E-Mail funktioniert 4. **Beim nächsten Speichern** wird das `password`-Feld automatisch entfernt --- ## Fail-Start Verhalten | Szenario | Ergebnis | |----------|----------| | `AZA_EMAIL_PASSWORD_0` gesetzt | E-Mail funktioniert | | `AZA_EMAIL_PASSWORD_0` nicht gesetzt | E-Mail-Abruf zeigt: "Konto-Daten unvollständig" | | Klartext-PW in JSON | Warnung + wird ignoriert | | GUI-Passworteingabe | Funktioniert für Sitzung (nicht persistent) | --- ## Testergebnis ``` 12/12 PASS, 0/12 FAIL GESAMTBEWERTUNG: PASS ``` | Test | Ergebnis | |------|----------| | Kein Passwort in JSON | PASS | | Warnung auf stderr bei Klartext | PASS | | Passwort NICHT in geladenen Daten | PASS | | ENV-PW in _password Feld | PASS | | Kein password Feld nach Laden | PASS | | Kein password in gespeicherter Datei | PASS | | Kein _password in gespeicherter Datei | PASS | | password entfernt (Konto 1) | PASS | | password entfernt (Konto 2) | PASS | | _password entfernt (nie auf Disk) | PASS | | Andere Felder erhalten | PASS | | Kein print mit password-Wert | PASS | --- ## Rest-Risiken 1. **Passwort im RAM:** Während der Sitzung liegt das Passwort im RAM (Python-String). Für eine Desktop-App akzeptabel. 2. **ENV-Variable sichtbar:** `AZA_EMAIL_PASSWORD_0` kann in Prozesslisten sichtbar sein. Empfehlung für Zukunft: OS-Keychain-Integration (Windows Credential Manager / macOS Keychain). 3. **Altes Passwort exponiert:** Das Passwort `Asdfasdf22@@As96k324` war in der JSON-Datei gespeichert. Es sollte beim Provider geändert werden. 4. **Backup-Dateien:** Die Kopie-Dateien (`aza_email - Kopie.py`, etc.) enthalten noch den alten Code. Diese sind Backups und nicht aktiv. --- ## Repo-Hygiene - Kein Git-Repository vorhanden → kein `.gitignore`-Eintrag nötig - Kein History-Rewrite nötig - `aza_email_config.json` wurde direkt bereinigt (Passwort entfernt)