From 9960d55a41eb9f791a7d2f4359ef84b5709a0cf8 Mon Sep 17 00:00:00 2001 From: pewdiepie-archdaemon Date: Wed, 3 Jun 2026 11:36:12 +0900 Subject: [PATCH] Decrypt CalDAV password before write-back (#1731) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit writeback_event read cfg["password"] (the encrypted blob) and passed it straight to DAVClient, so every local create/edit/delete authenticated with the literal ciphertext, the remote rejected it, and the change never reached the server — the exact silent-write-loss this module was built to prevent. The pull path src/caldav_sync.py already decrypts; mirror that. decrypt() is a no-op on legacy plaintext. Caught by #1731. --- src/caldav_writeback.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/caldav_writeback.py b/src/caldav_writeback.py index f20c2b4..1b6d6cc 100644 --- a/src/caldav_writeback.py +++ b/src/caldav_writeback.py @@ -157,10 +157,14 @@ async def writeback_event(owner: str, calendar_source: str, calendar_id: str, return {"skipped": "not a caldav calendar"} try: from routes.prefs_routes import _load_for_user + from src.secret_storage import decrypt cfg = (_load_for_user(owner) or {}).get("caldav", {}) or {} url = (cfg.get("url") or "").strip() user = (cfg.get("username") or "").strip() - pw = cfg.get("password") or "" + # Stored encrypted by routes/calendar_routes; decrypt before use so + # the remote sees the real password (decrypt is a no-op on legacy + # plaintext). The pull path src/caldav_sync.py already does this. + pw = decrypt(cfg.get("password") or "") if not (url and user and pw): return {"skipped": "caldav not configured"} result = await asyncio.to_thread(_writeback_blocking, calendar_id, ev, delete, url, user, pw)