Refuse to sign sessions with the committed fallback in production #27

Merged
martin merged 1 commit from claw/session-secret-required into main 2026-09-21 15:06:44 +00:00
Owner

SESSION_SECRET was never set on the service, so production signed every session cookie with development-secret-change-in-production — a value committed to this repo. mint-session.mjs, also committed, mints an admin session with that exact value, so anyone who could read the source could forge an admin cookie and skip Bio-ID.

The key is now resolved per call and a missing SESSION_SECRET throws in production instead of falling back. Local dev keeps the fallback, so mint-session.mjs still works there. verifySessionToken already catches, so a misconfigured deploy denies admin access rather than taking the site down.

Verified: tsc --noEmit clean. In production mode a forged dev-signed cookie is rejected, a missing secret refuses to mint, and a real secret round-trips; dev mode still mints and verifies.

Ships together with setting SESSION_SECRET as a service secret.

🤖 Generated with Claude Code

`SESSION_SECRET` was never set on the service, so production signed every session cookie with `development-secret-change-in-production` — a value committed to this repo. `mint-session.mjs`, also committed, mints an admin session with that exact value, so anyone who could read the source could forge an admin cookie and skip Bio-ID. The key is now resolved per call and a missing `SESSION_SECRET` throws in production instead of falling back. Local dev keeps the fallback, so `mint-session.mjs` still works there. `verifySessionToken` already catches, so a misconfigured deploy denies admin access rather than taking the site down. Verified: `tsc --noEmit` clean. In production mode a forged dev-signed cookie is rejected, a missing secret refuses to mint, and a real secret round-trips; dev mode still mints and verifies. Ships together with setting `SESSION_SECRET` as a service secret. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
SESSION_SECRET was never set on the service, so production signed every
session cookie with 'development-secret-change-in-production' — a value
committed to this repo. mint-session.mjs, also committed, mints an admin
session with that exact value, so anyone who could read the source could
forge an admin cookie and skip Bio-ID entirely.

Resolve the key per call and throw in production when SESSION_SECRET is
unset, instead of falling back. The fallback stays for local dev so
mint-session.mjs keeps working there. verifySessionToken already catches,
so a misconfigured deploy denies admin access rather than taking the site
down.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
martin merged commit 2a142349b6 into main 2026-09-21 15:06:44 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
martin/ballantyne-www!27
No description provided.