Every defense above depends on a secret or flag read from the environment, and the usual failure is silent: a missing CSRF_SECRET makes getSecret return undefined, a short one weakens the HMAC, and secure: true cookies vanish if NODE_ENV is misspelled. Validate configuration at startup with the schema library you use for requests, and refuse to boot on failure. Node reads .env natively with --env-file.
const Env = z.object({
NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),
PORT: z.coerce.number().int().min(1).max(65535).default(3000), // strings, coerced
SESSION_SECRET: z.string().min(32), CSRF_SECRET: z.string().min(32)
});
const parsed = Env.safeParse(process.env);
if (!parsed.success) { // fail fast, before the port is open
for (const i of parsed.error.issues) console.error(` ${i.path.join('.')}: ${i.message}`);
process.exit(1);
}
export const env = parsed.data;$ node --env-file=.env server.js # the file has CSRF_SECRET=short configuration error: CSRF_SECRET: Too small: expected string to have >=32 characters ($? = 1)
Import env everywhere instead of process.env. Keep .env out of the repository and the image, generate secrets with crypto.randomBytes(32).toString('base64url'), and prefer an array where rotation matters: cookieParser(['new', 'old']) and csrf-csrf 196 's getSecret both accept several, signing with the first and accepting any, so a key retires without logging everyone out.
npm 2,036 audit reads your lockfile against the GitHub 29 advisory database:
$ npm audit minimist 1.0.0 - 1.2.5 Severity: critical Prototype Pollution in minimist - https://github.com/advisories/GHSA-vh95-rmgr-6w4m node_modules/minimist 2 vulnerabilities (1 high, 1 critical). To address all issues, run: npm audit fix
Run it in CI as npm audit --omit=dev --audit-level=high so a build fails on a real production risk rather than a dev-only advisory nobody can exploit. Judging a package before installing it, install scripts, typosquatting, npm ci with a committed lockfile and Node's permission model are all Security and the Supply Chain. The Express-specific part is short: keep the middleware list small, because every entry runs on every request.