Sicherheit
Die Anwendung ist für den Betrieb auf einem Rechner durch einen Administrator ausgelegt. Sie bindet ausschließlich an 127.0.0.1, speichert keine Microsoft-Passwörter und verschlüsselt alle gespeicherten Geheimnisse.
| Schutzobjekt | Maßnahme |
|---|---|
| Administratorpasswort | Argon2id-Hash in .env, kein Standardpasswort |
| Sitzung | signiertes Cookie, HttpOnly, SameSite=Lax |
| Schreibende Requests | CSRF-Token im Header |
| Tokens und Passwörter | Fernet-verschlüsselt in der Datenbank |
| Laufzeit-Geheimnisse | temporäre Dateien mit restriktiven Rechten |
| Protokolle | Redaktion vor dem Schreiben |
| Netzwerk | Bindung an 127.0.0.1, TLS-Prüfung immer aktiv |
| Updates | Ed25519-signierte Prüfsummen |
Schlüssel und Konfiguration
| Wert | Zweck |
|---|---|
ADMIN_PASSWORD_HASH |
Argon2id-Hash des Administratorpassworts |
APP_ENCRYPTION_KEY |
Fernet-Schlüssel für Tokens und Passwörter |
SESSION_SECRET |
Signatur der Sitzungs-Cookies (mindestens 32 Zeichen) |
Fehlt einer dieser Werte, startet die Anwendung nicht. Es gibt kein Default-Passwort und keinen Default-Schlüssel.
chmod 600 .env
chmod 700 .
Unter Windows die Vererbung entfernen und nur dem ausführenden Benutzer, SYSTEM und Administratoren Zugriff geben:
icacls .env /inheritance:r /grant:r "%USERNAME%":F SYSTEM:F Administrators:F
Verschlüsselung gespeicherter Geheimnisse
Mit Fernet (APP_ENCRYPTION_KEY) verschlüsselt werden der MSAL-Token-Cache je Microsoft-Konto (identities.encrypted_token_cache), Zielpasswörter am Zielserver (targets.encrypted_default_password), Zielpasswörter je Migration (jobs.encrypted_target_password) und Quellpasswörter für IMAP-Quellen.
In der Datenbank steht nur Ciphertext. Kein Antwortmodell enthält ein Passwort; sichtbar ist höchstens, ob eines hinterlegt ist. Ein PATCH ohne Passwortfeld lässt den gespeicherten Wert unverändert.
Keyverlust: Geht APP_ENCRYPTION_KEY verloren oder wird er ersetzt, sind alle gespeicherten Tokens und Passwörter unlesbar. Eine Wiederherstellung ist bewusst nicht vorgesehen; betroffene Konten und Ziele müssen neu hinterlegt werden. Die .env daher sichern, aber getrennt von der Datenbank.
Anmeldung und Sitzung
- Geprüft wird der Argon2id-Hash; falscher Benutzername und falsches Passwort sind nicht unterscheidbar (gleiche Meldung, beide Prüfungen laufen immer).
- Fehlversuche werden pro Client-IP gezählt (Standard: 5 in 15 Minuten). Danach
429mitRetry-After; ein erfolgreicher Login setzt den Zähler zurück. Der Zähler liegt im Prozessspeicher und ist nach einem Neustart leer. - Cookie
m365sync_session: signiert,HttpOnly,SameSite=Lax,Path=/,Secureautomatisch beihttps://. - Laufzeit 8 Stunden (
SESSION_TTL_SECONDS, Standard 28800).
Bekannte Grenze: Beim Abmelden wird das Cookie im Browser gelöscht. Eine bereits kopierte Kopie bleibt bis zum Ablauf gültig, weil es keine serverseitige Sitzungstabelle gibt. Bei Bedarf hilft eine Rotation von SESSION_SECRET (meldet alle Sitzungen ab).
CSRF-Schutz
Der CSRF-Token steckt im signierten Cookie-Payload und wird der Oberfläche über die Login-Antwort bzw. GET /api/v1/auth/me mitgeteilt. Jeder schreibende Request muss ihn im Header X-CSRF-Token mitschicken; verglichen wird mit secrets.compare_digest gegen den signierten Wert. Fehlt oder passt er nicht: 403 csrf_failed. Der Schutz hängt damit an der Sitzung; ein Angreifer müsste das signierte Cookie fälschen, nicht nur ein zweites Cookie setzen.
Temporäre Secret-Dateien
Während eines Laufs werden Access-Token und Passwörter unter data/tmp/<run-id>/ geschrieben (access_token, target_password, source_password).
- Dateien
0600, Verzeichnis0700(POSIX). - Unter Windows setzt die Anwendung eine explizite DACL (
icacls /inheritance:r /grant:rfür Benutzer,SYSTEM,Administratoren), weilchmoddort wirkungslos ist. - Keine Geheimnisse in der Prozessliste: imapsync erhält nur Dateipfade (
--oauthaccesstoken1,--passfile1,--passfile2). - Löschung im
finally-Block, auch bei Abbruch oder Fehler; veraltete Dateien werden beim Start aufgeräumt.
Protokolle
Laufprotokolle werden vor dem Schreiben redigiert. Entfernt werden Access-Tokens, Bearer- und XOAUTH2-Muster, Passwörter und bekannte Secret-Werte; die Pfade der temporären Dateien bleiben sichtbar, ihre Inhalte nicht. Protokolle enthalten dennoch Metadaten wie E-Mail-Adressen, Hostnamen, Ordnernamen und imapsync-Statistiken. Das Log-Verzeichnis ist deshalb wie die Datenbank zu schützen.
Netzwerk
- Der Server bindet ausschließlich an
127.0.0.1; es gibt keinen externen Listener. - Für LAN- oder Internetzugriff ist ein separater HTTPS-Reverse-Proxy nötig. Dann
APP_BASE_URLaufhttps://…setzen, damit das CookieSecurewird. - Die TLS-Prüfung zu IMAP-Servern wird nie deaktiviert. Selbstsignierte Zertifikate führen zu einem Fehler, nicht zu einer stillen Ausnahme.
- Als Ziel gesperrt sind
localhost, Loopback- und Link-Local-Adressen.
Updates
Der Updater akzeptiert nur Releases, deren SHA256SUMS mit dem eingebetteten Ed25519-Schlüssel signiert ist. Dateiprüfsummen werden erst nach gültiger Signatur ausgewertet; vor dem Austausch werden .env und Datenbank gesichert, bei einem Fehler wird zurückgerollt. Details: Updates.
Datenhaltung und Löschung
data/database/app.db Konfiguration, Konten, Jobs, Läufe, verschlüsselte Geheimnisse
data/logs/ Laufprotokolle
data/tmp/ temporäre Dateien (werden gelöscht)
data/updates/ Update-Sicherungen
.env Schlüssel und Passwort-Hash
Ein Backup muss .env und data/ umfassen; ohne .env sind die verschlüsselten Werte nicht lesbar.
Löschen des Ordners entfernt alle Daten — Datenbank, Tokens, Passwörter, Protokolle und Schlüssel. Es gibt keine versteckten Kopien in AppData, ProgramData, der Registry oder als Dienst. Vor dem Löschen sichern, wenn die Daten noch gebraucht werden.
Nicht vorhanden
Keine Mehrbenutzerverwaltung und keine Rollen (genau ein Administrator), keine Zwei-Faktor-Authentifizierung für die lokale Anmeldung, kein zentrales Audit-Log über Konfigurationsänderungen (protokolliert werden Anmeldungen und Migrationsläufe) und keine Verschlüsselung der gesamten Datenbank — nur die genannten Geheimnisfelder sind verschlüsselt.