Skip to content

fix(dashboard-api): prune magic-link rate limit buckets to prevent memory leak#1670

Merged
Lightheartdevs merged 3 commits into
Osmantic:mainfrom
HimanshuShukla671:fix/magic-link-rate-limit-leak
Jul 9, 2026
Merged

fix(dashboard-api): prune magic-link rate limit buckets to prevent memory leak#1670
Lightheartdevs merged 3 commits into
Osmantic:mainfrom
HimanshuShukla671:fix/magic-link-rate-limit-leak

Conversation

@HimanshuShukla671

Copy link
Copy Markdown

Description

Fixes a memory leak in the magic link rate limiter.

The _RATE_LIMIT_BUCKETS dictionary was accumulating IP addresses indefinitely because expired buckets were just having their count set to 0 instead of being popped. If a bot or scanner hits this endpoint from many unique IPs over time, this dictionary would grow indefinitely.

This PR does two things:

  1. Prunes stale rate limit buckets if the dictionary grows beyond 1000 entries (and forcefully clears it if it grows beyond 10000 during a DDoS).
  2. Uses pop() instead of setting the count to 0 when an IP's window expires.

@Lightheartdevs

Copy link
Copy Markdown
Collaborator

Thanks for tightening the magic-link failure limiter; bounding that in-memory bucket map is the right direction for this auth surface.

Advisory status: not ready yet

Quickest path to merge:

  • Add regressions in ods/extensions/services/dashboard-api/tests/test_magic_link.py for the new bucket lifecycle: expired buckets are removed instead of reset to (0, now), stale entries are pruned once _RATE_LIMIT_BUCKETS grows past 1000, and the emergency clear path trips once it remains above 10000.
  • Keep the production change in ods/extensions/services/dashboard-api/routers/magic_link.py focused on this limiter behavior. The lock/list-delete structure looks reasonable; the missing piece is test coverage for the new memory-bound guarantees on the public redemption path.

What I checked:

  • Static review of _check_rate_limit() and _record_failure() plus the existing magic-link rate-limit test coverage.
  • GitHub checks for this head are green: API tests, ruff, mypy, dashboard build, matrix smoke, secret scan, shell/PowerShell lint, and env validation.
  • git diff --check origin/main...pr-1670 passed.

Thanks again for pushing this auth hardening forward.

@HimanshuShukla671

Copy link
Copy Markdown
Author

I've added the requested regression tests in test_magic_link.py to cover the new bucket lifecycle (verifying that expired buckets are removed, stale entries are pruned once the bucket map exceeds 1000, and the emergency clear trips above 10000). I also fixed a minor ruff formatting issue that was causing the Python Lint workflow to fail.

Let me know if there's anything else needed!

@Lightheartdevs

Copy link
Copy Markdown
Collaborator

Thanks for adding the magic-link limiter regressions after the first advisory pass.

Advisory status: looks merge-ready

What looks good:

  • ods/extensions/services/dashboard-api/routers/magic_link.py now removes expired buckets instead of preserving empty entries and bounds the in-memory bucket map under high-cardinality failure traffic.
  • ods/extensions/services/dashboard-api/tests/test_magic_link.py covers the expired-bucket removal, stale pruning threshold, and emergency clear path that the earlier review asked for.
  • GitHub’s visible CI is green for the updated head, including dashboard API tests, Python lint/type checks, shell/PowerShell lint, matrix smoke, integration smoke, and env validation.

What I checked:

  • Updated diff and prior advisory thread.
  • python -m pytest tests/test_magic_link.py -q from ods/extensions/services/dashboard-api: 55 passed.
  • git diff --check origin/main...HEAD passed.
  • gh pr checks 1670: visible checks passing.

Thanks again for tightening this auth surface.

@Lightheartdevs Lightheartdevs merged commit 89003ea into Osmantic:main Jul 9, 2026
32 checks passed
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.

2 participants