fix(api): evict only non-rate-limited entries when rate limiter map exceeds capacity#1736
Open
MinitJain wants to merge 2 commits intoCapSoftware:mainfrom
Open
fix(api): evict only non-rate-limited entries when rate limiter map exceeds capacity#1736MinitJain wants to merge 2 commits intoCapSoftware:mainfrom
MinitJain wants to merge 2 commits intoCapSoftware:mainfrom
Conversation
Previous code called requestCounts.clear() when size exceeded 10k entries after pruning expired ones, resetting rate limit state for all clients including those already being blocked. Now evicts only entries with count below the rate limit threshold, stopping once size is within bounds. Clients at or above the limit keep their state. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rate-limited Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
requestCounts.clear()was called when the in-memory rate limiter map exceeded 10,000 entries after pruning expired onescount < RATE_LIMIT_MAX_REQUESTS(clients not yet at the limit) until the map is back within boundsTest plan
🤖 Generated with Claude Code
Greptile Summary
This PR replaces the unsafe
requestCounts.clear()call with targeted eviction that preserves rate-limited client state, correctly preventing rate-limited clients from bypassing the limit after an eviction cycle.count < RATE_LIMIT_MAX_REQUESTSand stops once the map is back withinRATE_LIMIT_MAX_ENTRIES. If all remaining entries are at or above the limit, nothing is evicted and the map stays over capacity — there is no fallback path, so memory can grow unbounded within a single 60-second window under adversarial load.Confidence Score: 4/5
Safe to merge with awareness of the edge-case memory growth when all entries are rate-limited.
The core security fix is correct and well-reasoned. The one remaining P2 concern — no fallback when targeted eviction leaves the map over capacity — is an edge case that only materialises under adversarial load with >10,000 unique IPs, and entries self-expire after 60 s anyway. Scored 4 rather than 5 to surface that the capacity bound is no longer hard-guaranteed.
apps/web/app/api/utils.ts — eviction fallback path
Important Files Changed
requestCounts.clear()with targeted eviction of non-rate-limited entries; fixes the security bypass but lacks a fallback when all entries are at the rate limit.Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A[Every 100th request] --> B[Prune expired entries\nnow > v.resetAt] B --> C{requestCounts.size\n> RATE_LIMIT_MAX_ENTRIES?} C -- No --> G[Continue to request handling] C -- Yes --> D[Iterate map entries in insertion order] D --> E{size <=\nRATE_LIMIT_MAX_ENTRIES?} E -- Yes --> G E -- No --> F{v.count <\nRATE_LIMIT_MAX_REQUESTS?} F -- Yes --> H[Delete entry\nsize--] F -- No\nrate-limited client --> I[Skip entry\nsize unchanged] H --> E I --> J{More entries?} J -- Yes --> E J -- No\nall entries rate-limited --> K[Loop ends — map may\nstill exceed capacity] K --> GPrompt To Fix All With AI
Reviews (1): Last reviewed commit: "fix(api): evict only non-rate-limited en..." | Re-trigger Greptile