fix(auth): prune expired sessions on every verify to prevent memory leak - #196
Conversation
The in-memory _sessions dict accumulated expired tokens indefinitely — entries were only removed when that specific token was verified. Add a lazy _prune_expired_sessions() call at the top of verify_session() so all expired entries are swept during normal traffic. Addresses nesquena#192.
|
Thanks for this — the fix is correct and the approach is right. A few notes from reviewing What's good:
One thing to check: Tests: The PR description says existing tests pass, but I don't see new unit tests specifically for the prune behavior added in Overall this is a clean, minimal fix for a real issue. Ready for maintainer review. |
Tests verify: - Fresh session creation and validation - Expired entries are pruned during verify_session() calls - Valid sessions are never removed by pruning - Empty dict is safe for pruning - Session TTL matches expected 24-hour window - invalidate_session() actually removes the token - Invalidating non-existent tokens is safe
Full Review: PR #196 — prune expired auth sessionsThanks @iRonin! Solid fix for a real memory leak. Security AuditClean. The change is limited to session cleanup logic. No new endpoints, no external resources, no injection vectors. Code ReviewThe One edge case to note: under very high concurrent auth load, the dict iteration in TestsExcellent test suite — 8 unit tests covering: valid session creation, expired session pruning, valid sessions preserved, prune-before-verify ordering, empty dict safety, TTL verification, invalidation, and unknown-token invalidation. Well-structured with proper setUp cleanup. One concern with the test setup: Test Results514 passed, 0 failed, 41 skipped. No regressions. VerdictApproved. Ready to merge. |
|
Thank you, @iRonin! Six security PRs in a row — each one catching a real production issue. Session memory leak, CSP headers, connection timeout, HTTPS/TLS support, update branch tracking, CLI session API. This kind of focused, no-nonsense security hardening is exactly what a self-hosted tool needs. We've added you to the Contributors section in the README. Thank you. |
…eak (nesquena#196) * fix(auth): prune expired sessions on every verify to prevent memory leak The in-memory _sessions dict accumulated expired tokens indefinitely — entries were only removed when that specific token was verified. Add a lazy _prune_expired_sessions() call at the top of verify_session() so all expired entries are swept during normal traffic. Addresses nesquena#192. * test(auth): add 8 unit tests for session lifecycle and lazy pruning Tests verify: - Fresh session creation and validation - Expired entries are pruned during verify_session() calls - Valid sessions are never removed by pruning - Empty dict is safe for pruning - Session TTL matches expected 24-hour window - invalidate_session() actually removes the token - Invalidating non-existent tokens is safe
…eak (nesquena#196) * fix(auth): prune expired sessions on every verify to prevent memory leak The in-memory _sessions dict accumulated expired tokens indefinitely — entries were only removed when that specific token was verified. Add a lazy _prune_expired_sessions() call at the top of verify_session() so all expired entries are swept during normal traffic. Addresses nesquena#192. * test(auth): add 8 unit tests for session lifecycle and lazy pruning Tests verify: - Fresh session creation and validation - Expired entries are pruned during verify_session() calls - Valid sessions are never removed by pruning - Empty dict is safe for pruning - Session TTL matches expected 24-hour window - invalidate_session() actually removes the token - Invalidating non-existent tokens is safe
Summary
The in-memory
_sessionsdictionary inapi/auth.pyaccumulated expired session tokens indefinitely. Each login added a new entry with a 24-hour TTL, but only the specific token being verified was ever checked for expiry. All other expired entries persisted in memory for the lifetime of the server process.Fix
Added
_prune_expired_sessions()which removes all entries past their TTL. Called at the top ofverify_session()so cleanup happens lazily during normal authenticated traffic — no background thread needed, zero overhead when no sessions have expired.Testing
len(_sessions)no longer grows monotonically after multiple login cyclesFixes #192