mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-15 17:25:26 -04:00
fix(security): encrypt CardDAV password at rest in settings.json (#1741)
* fix(security): encrypt CardDAV password at rest in settings.json CardDAV password was stored in plaintext in data/settings.json, while other secrets (email, CalDAV) are encrypted using src.secret_storage. On read (_get_carddav_config): decrypt the password via decrypt(). On write (update_config): encrypt the password via encrypt() before saving to settings.json. decrypt() is a no-op on plaintext, so existing deployments upgrade transparently on the first read after the next config save. * test: add coverage for CardDAV password encryption Nine tests covering: - encrypt-on-save and decrypt-on-read round-trip - encrypted value is stored with enc: prefix (plaintext absent from file) - legacy plaintext passthrough - CARDDAV_PASSWORD env var passthrough (not decrypted) - empty password / no settings file - double-save does not corrupt - encrypt() idempotent on already-encrypted value
This commit is contained in:
@@ -45,10 +45,14 @@ def _save_settings(settings):
|
||||
def _get_carddav_config():
|
||||
import os
|
||||
settings = _load_settings()
|
||||
password = settings.get("carddav_password", os.environ.get("CARDDAV_PASSWORD", ""))
|
||||
if password and "carddav_password" in settings:
|
||||
from src.secret_storage import decrypt
|
||||
password = decrypt(password)
|
||||
return {
|
||||
"url": settings.get("carddav_url", os.environ.get("CARDDAV_URL", "")),
|
||||
"username": settings.get("carddav_username", os.environ.get("CARDDAV_USERNAME", "")),
|
||||
"password": settings.get("carddav_password", os.environ.get("CARDDAV_PASSWORD", "")),
|
||||
"password": password,
|
||||
}
|
||||
|
||||
|
||||
@@ -785,7 +789,11 @@ def setup_contacts_routes():
|
||||
except ValueError as e:
|
||||
raise HTTPException(400, str(e))
|
||||
else:
|
||||
settings[key] = data[key]
|
||||
value = data[key]
|
||||
if key == "carddav_password" and value:
|
||||
from src.secret_storage import encrypt
|
||||
value = encrypt(value)
|
||||
settings[key] = value
|
||||
_save_settings(settings)
|
||||
# Force re-fetch
|
||||
_contact_cache["fetched_at"] = None
|
||||
|
||||
Reference in New Issue
Block a user