🚦 fix: Fail Fast on Missing SESSION_SECRET, Harden Session Read#85
Merged
Conversation
dustinhealy
approved these changes
Jun 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When the admin panel runs in production with a missing or empty
SESSION_SECRET, the failure is extremely confusing.src/server/session.tsthrows at module-evaluation time, but that module is only imported lazily by the auth server-function chunk. So:Admin panel listening...).SESSION_SECRET environment variable must be set.Server function module export not resolved for serverFn ID: ..., because Bun returns the cached, half-evaluated auth module whose handler exports are allundefined:This reads like a build/bundler bug and sends you chasing the wrong thing. It works under
bun devonly because development falls back toDEV_SECRET.Changes
server.ts— fail fast at boot. ValidateSESSION_SECRET(non-empty, ≥32 chars) beforeBun.servewhen not in development, and exit with a clear message instead of booting into the lazy-throw trap. This is the same constraintsession.tsalready enforces, just surfaced immediately and legibly.src/server/auth.ts— hardengetCurrentUserFn. It read the session with no error handling, so any session-read failure became an unhandled 500. It now mirrorsverifyAdminTokenFnand returns a logged-out result ({ user: null, isAuthenticated: false }) on failure.On graceful sign-out
A corrupt/undecryptable
admin-sessioncookie is already handled well: h3 ignores the unseal error, starts a fresh session, and overwrites the bad cookie (verified — a garbage cookie yields a clean logged-out200). The case where a stale session lingers isverifyAdminTokenFnintentionally keeping the cached session when the LibreChat backend is unreachable or returns a non-401/403 error, to avoid logging admins out on transient blips. I left that policy as-is on purpose; happy to revisit if you'd prefer it to sign out after a sustained revalidation failure.Testing
bunx vitest run src/server/auth.oauth.test.ts src/server/session.test.ts→ 9/9 pass.NODE_ENV=production SESSION_SECRET="" bun server.tsexits1withSESSION_SECRET must be set to at least 32 characters (got 0). Refusing to start.Admin panel listening...).module export not resolvedcascade against the published image with an empty secret, and confirmed it disappears once a valid secret is set.