From e36d7121f19807209a88bb760c1a9404db46cd2c Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 15 Mar 2026 18:54:37 +0200 Subject: [PATCH] fix(desktop): broken due to CSRF failing --- apps/server/src/routes/csrf_protection.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/server/src/routes/csrf_protection.ts b/apps/server/src/routes/csrf_protection.ts index b7c5f8d5cb..17cba503a2 100644 --- a/apps/server/src/routes/csrf_protection.ts +++ b/apps/server/src/routes/csrf_protection.ts @@ -1,4 +1,5 @@ import { doubleCsrf } from "csrf-csrf"; + import sessionSecret from "../services/session_secret.js"; import { isElectron } from "../services/utils.js"; @@ -13,7 +14,11 @@ const doubleCsrfUtilities = doubleCsrf({ httpOnly: !isElectron // set to false for Electron, see https://github.com/TriliumNext/Trilium/pull/966 }, cookieName: CSRF_COOKIE_NAME, - getSessionIdentifier: (req) => req.session.id + // In Electron, API calls go through an IPC bypass (routes/electron.ts) that uses a + // FakeRequest with a static session ID, while the bootstrap request goes through real + // Express with a real session. This mismatch causes CSRF validation to always fail. + // Since Electron is a local single-user app, a constant identifier is acceptable here. + getSessionIdentifier: (req) => isElectron ? "electron" : req.session.id }); export const { generateCsrfToken, doubleCsrfProtection } = doubleCsrfUtilities;