/api/ai/overview has no rate limiting, unlike sibling analyze/briefing endpoints — shared Gemini key pool exhaustion
Problem
src/app/api/ai/overview/route.ts (POST handler, ~line 308) calls the same Gemini client / API key pool (createGeminiClient, rotateApiKey) as src/app/api/ai/analyze/route.ts and src/app/api/ai/briefing/route.ts. Both siblings implement a 5-req/min-per-IP rate limiter before calling Gemini. overview implements none — confirmed by inspection, there is no rate-limit or getClientIp reference anywhere in the file.
Impact
Any unauthenticated caller can POST unbounded requests to /api/ai/overview, each triggering a real Gemini API call against the shared GEMINI_API_KEY_* credentials. Because analyze, briefing, and overview rotate through the same key pool, exhausting quota/cost via overview degrades or breaks the other two endpoints as well, even though those two are individually rate-limited. Net effect: a low-effort denial-of-service on all AI features plus direct API cost, reachable through the one endpoint in the trio that was left unguarded. Relation to existing issues This is distinct from #242 ("rate limiters trust client-supplied X-Forwarded-For… CWE-807", closed not_planned). #242 covers spoofing a limiter that exists on analyze/briefing/sweep/etc. This issue is that overview has no limiter to spoof in the first place. Fixing #242's underlying getClientIp helper would not by itself close this gap — overview would still need the limiter added.
Suggested fix
Add the same per-IP rate-limit check used in analyze/briefing to overview. Given the limiter logic is currently duplicated (and inconsistently applied) across these routes, consider extracting a shared checkRateLimit(ip) helper built on getClientIp from src/lib/ssrf-guard.ts, so all three AI routes share one implementation and a future route can't be silently left unguarded again. Note: if/when #242 is addressed, the shared helper should also inherit that fix rather than requiring a second pass.
References
- src/app/api/ai/overview/route.ts
- src/app/api/ai/analyze/route.ts (reference pattern, rate limiter + IP extraction)
- src/app/api/ai/briefing/route.ts (same)
- src/lib/ssrf-guard.ts (getClientIp)
Source: simplifaisoul/osiris