Skip to content

Persist login rate limit attempts#1919

Closed
franksong2702 wants to merge 1 commit into
nesquena:masterfrom
franksong2702:franksong2702/issue-1910-persist-login-rate-limit
Closed

Persist login rate limit attempts#1919
franksong2702 wants to merge 1 commit into
nesquena:masterfrom
franksong2702:franksong2702/issue-1910-persist-login-rate-limit

Conversation

@franksong2702

Copy link
Copy Markdown
Contributor

Thinking Path

Issue #1910 points out that the login rate limiter currently stores failed attempts only in process memory. A server restart clears the window, weakening the limiter for deployments with password auth enabled.

What Changed

  • Persist login-attempt buckets to STATE_DIR/.login_attempts.json.
  • Load persisted attempts at startup and prune entries outside the configured window.
  • Write attempts atomically with a temp file + os.replace, matching the existing session-cookie persistence pattern.
  • Store the file with 0600 permissions.
  • Avoid retaining empty IP buckets after pruning.
  • Add regression tests for persistence, expiry pruning, file permissions, and reload behavior.

Why It Matters

Password-auth deployments keep the same failed-attempt window across normal restarts instead of granting every IP a fresh bucket whenever the WebUI process restarts.

Verification

  • .venv_test/bin/python -m pytest -q tests/test_issue1910_login_attempt_persistence.py tests/test_sprint29.py::TestLoginRateLimit
  • python3 -m py_compile api/auth.py
  • git diff --check

Risks

Low. The limiter remains single-process and keeps the same threshold/window semantics. If the file is missing, malformed, or unwritable, the auth path falls back to the current in-memory behavior and logs at debug level.

Model Used

GPT-5 Codex via Codex CLI.

Closes #1910.

@nesquena-hermes

Copy link
Copy Markdown
Collaborator

Shipped in v0.51.29 via the Release F batch (release PR #1934, merge SHA 596c6b3). Your work is now live on master.

🚀 Release notes: https://github.com/nesquena/hermes-webui/releases/tag/v0.51.29

Thanks for the contribution!

pull Bot pushed a commit to soitun/hermes-webui that referenced this pull request May 8, 2026
pull Bot pushed a commit to soitun/hermes-webui that referenced this pull request May 8, 2026
…persistence + scroll/lineage fixes + i18n cleanup)

Six-PR contributor batch:
- PR nesquena#1919 (franksong2702): Persist login rate limit attempts (closes nesquena#1910)
- PR nesquena#1920 (franksong2702): Remove dead Kanban start i18n key
- PR nesquena#1921 (Michaelyklam): Production Docker image hardening (closes nesquena#1908)
- PR nesquena#1926 (ai-ag2026): Prevent chat scroll resets after final render
- PR nesquena#1927 (ai-ag2026): Preserve viewport when loading older messages
- PR nesquena#1930 (ai-ag2026): Collapse stale compression sidebar segments

Tests: 4947 → 4960 (+13 net new). Browser API harness all-green.
Opus advisor: SHIP-READY. CHANGELOG conflict on nesquena#1919 auto-resolved
during stage rebase (CHANGELOG took ours strategy).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

security(auth): persist login rate limiter across restarts

2 participants