Timeout warning ≥2min before expiration with extend option
Why it matters
A session that expires silently while a user is mid-transaction forces an abrupt authentication failure — potentially losing form data, a partially entered transfer, or an in-flight payment. Without a warning, users either encounter jarring redirects or, worse, begin abandoning financial tasks they cannot complete. CWE-613 and PCI-DSS Req 8.2.8 require that session expiration be communicated to users. Beyond compliance, an unwarned expiry increases the probability that users disable session timeouts through workarounds, defeating the security control entirely. A 2-minute warning with an 'extend' option preserves both security and usability.
Severity rationale
Medium because silent expiry during active financial tasks creates UX failures that drive users to circumvent session security controls, indirectly undermining the inactivity timeout that PCI-DSS Req 8.2.8 mandates.
Remediation
Add a warning modal component in src/components/SessionWarning.tsx that fires at 120 seconds before the session expiration boundary:
// lib/sessionWarning.ts
export function useSessionWarning(sessionTimeoutSeconds: number) {
const [showWarning, setShowWarning] = useState(false);
useEffect(() => {
const warningMs = (sessionTimeoutSeconds - 120) * 1000; // 2 min before expiry
const timer = setTimeout(() => setShowWarning(true), warningMs);
return () => clearTimeout(timer);
}, [sessionTimeoutSeconds]);
const handleExtend = async () => {
await fetch('/api/auth/extend-session', { method: 'POST' });
setShowWarning(false);
};
return { showWarning, handleExtend };
}
The modal must present at least two choices: extend (calls the server) and logout. A countdown timer inside the modal is strongly recommended so the user knows how many seconds remain.
Detection
- ID:
timeout-warning - Severity:
medium - What to look for: Count all timeout warning components, modals, or notifications in the frontend code. Quote the actual warning trigger time (in seconds before expiration). Verify the warning appears at least 120 seconds (2 minutes) before expiration. Count the options offered (extend, logout). A warning less than 120 seconds before expiration does not count as pass.
- Pass criteria: At least 1 timeout warning is shown at least 120 seconds (2 minutes) before session expiration. Warning includes at least 2 options: extend session and logout. Report the count even on pass (e.g., "1 warning modal at 120s before expiry, 2 options: 'Continue Working' and 'Logout'").
- Fail criteria: No timeout warning exists (0 components), or warning appears less than 120 seconds before expiration, or warning lacks an extend option.
- Skip (N/A) when: The application has no financial operations requiring session timeouts — cite the actual project type found.
- Detail on fail:
"0 timeout warning components found — session expires without user notification"or"Warning at 30 seconds — below 120 second minimum" - Remediation: Implement a timeout warning modal that triggers 2 minutes before session expiration (in
src/components/SessionWarning.tsx):// lib/sessionWarning.ts export function useSessionWarning(sessionTimeout: number) { const [showWarning, setShowWarning] = useState(false); useEffect(() => { const warningTime = (sessionTimeout - 2 * 60) * 1000; // 2 min before expiry const timer = setTimeout(() => setShowWarning(true), warningTime); return () => clearTimeout(timer); }, [sessionTimeout]); const handleExtend = async () => { await fetch('/api/auth/extend-session', { method: 'POST' }); setShowWarning(false); }; return { showWarning, handleExtend }; }
External references
- cwe · CWE-613 — Insufficient Session Expiration
- pci-dss:4.0 · Req 8.2.8
Taxons
History
- 2026-04-18·v1.0.0·Initial import from finserv-session-security·automated