From d0b57b6fa37bc887bbc0c94d96ebcaf127a70733 Mon Sep 17 00:00:00 2001 From: Matt Davidson Date: Thu, 16 Jul 2026 13:45:31 -0700 Subject: [PATCH] Pre-public hardening: secure cookies in production, widen .gitignore - Session cookie gets secure: true (with trust proxy) under NODE_ENV=production instead of relying on a comment telling the reader to flip it - Ignore all .env* variants except .env.example so adapted clones can't accidentally commit .env.local / .env.production --- .gitignore | 3 ++- src/app.ts | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 4c588b7..e5f60cb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ node_modules/ dist/ -.env +.env* +!.env.example *.tsbuildinfo .DS_Store npm-debug.log* diff --git a/src/app.ts b/src/app.ts index 4905b2d..2a53332 100644 --- a/src/app.ts +++ b/src/app.ts @@ -19,8 +19,13 @@ export function createApp(): express.Express { // Demo-only session setup: the default in-memory store loses sessions on // restart and doesn't scale past one process — use a shared store (e.g. - // connect-redis) in production, and set cookie.secure (plus - // app.set('trust proxy', 1) behind a proxy) once you're serving over HTTPS. + // connect-redis) in production. Secure (HTTPS-only) cookies switch on via + // NODE_ENV=production; trust proxy lets Express see the original protocol + // behind a TLS-terminating proxy so the cookie still gets set. + const isProduction = process.env.NODE_ENV === "production"; + if (isProduction) { + app.set("trust proxy", 1); + } app.use( session({ secret: config.sessionSecret, @@ -28,6 +33,7 @@ export function createApp(): express.Express { saveUninitialized: false, cookie: { httpOnly: true, + secure: isProduction, // 'lax', not 'strict': the SSO callback arrives as a top-level GET // redirect from WorkOS, and 'strict' would drop the session cookie on // that navigation — breaking the state check.