Summary
verifySession only checks that the user exists and is active; there is no session-epoch / passwordChangedAt mechanism. A password reset performed to recover a compromised account does not invalidate already-issued session cookies on other devices, and an admin "force reset" cannot kick an active attacker. The short 1-hour prod cookie lifetime limits blast radius, but there is no "log out everywhere" guarantee.
Affected code
app/features/authentication/server/session.server.ts
app/features/authentication/server/reset-account-password.server.ts
app/features/authentication/server/change-account-password.server.ts
Remediation
Add a sessionEpoch column, embed it in the session, reject stale epochs in verifySession, and bump it on every password change/reset and admin invalidation.
Severity
Medium.
Source: internal security review (commit 0360e87, 2026-07-21).
Summary
verifySessiononly checks that the user exists and is active; there is no session-epoch /passwordChangedAtmechanism. A password reset performed to recover a compromised account does not invalidate already-issued session cookies on other devices, and an admin "force reset" cannot kick an active attacker. The short 1-hour prod cookie lifetime limits blast radius, but there is no "log out everywhere" guarantee.Affected code
app/features/authentication/server/session.server.tsapp/features/authentication/server/reset-account-password.server.tsapp/features/authentication/server/change-account-password.server.tsRemediation
Add a
sessionEpochcolumn, embed it in the session, reject stale epochs inverifySession, and bump it on every password change/reset and admin invalidation.Severity
Medium.
Source: internal security review (commit
0360e87, 2026-07-21).