You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(rate_limit): eviction fires after new entry insertion, allowing attacker to escape rate-limit cap #243
The _windows eviction in rate_limit.py fires after the new entry is already inserted into the dict. When eviction is triggered, the sorted key list includes the newly added entry, and the eviction routine may delete that new entry immediately — resetting the caller's counter to zero and allowing them to bypass the limit entirely.
Root Cause
backend/app/security/rate_limit.py around line 67:
self._windows[key] =window# ← new entry inserted firstiflen(self._windows) >self._MAX_WINDOW_ENTRIES:
# sorted_keys includes the brand-new entrysorted_keys=sorted(self._windows, key=lambdak: self._windows[k].last_seen)
forkinsorted_keys[: len(sorted_keys) //2]:
delself._windows[k] # ← may delete the entry just added above
If the new entry's last_seen is the oldest (e.g., first-ever request from this credential during an eviction triggered by the 25,001st unique key), it lands at the front of sorted_keys and is evicted immediately, resetting the caller's rate-limit window to nothing.
The attacker's counter is reset to 0. Next request starts a clean window.
Repeat indefinitely: attacker can send unlimited requests at the rate of one per eviction cycle.
Proposed Fix
# Insert AFTER eviction, not before:iflen(self._windows) >=self._MAX_WINDOW_ENTRIES:
sorted_keys=sorted(self._windows, key=lambdak: self._windows[k].last_seen)
forkinsorted_keys[: len(sorted_keys) //2]:
delself._windows[k]
self._windows[key] =window# ← insert after eviction
Also add a test that verifies the newly inserted key survives an eviction cycle:
deftest_eviction_does_not_delete_new_entry():
rl=RateLimiter(...)
# fill to MAX_WINDOW_ENTRIES - 1 with dummy keys# trigger eviction by adding the MAX+1 key# assert the MAX+1 key still exists and its count is correct
Activity
piyushmakhija28 commentedon Jun 21, 2026
Fixed in PR #280 (Sprint R3/R4: fix(sprint-r3): root-cause fixes for all 39 bugs from code review round 3 + Sprint R4 round 4)