Description
while reading through the ai/roast route i noticed it has no session check at all and no rate limiting, so anyone on the internet can hit it and spam gemini calls.
The Problem
src/app/api/ai/roast/route.ts:7-19: POST handler goes straight from req.json() into genAI.getGenerativeModel(...) and model.generateContent(prompt). there is no getServerSession, no bearer token check, no ip rate limit, no per-user quota. GEMINI_API_KEY is read at module load on line 5.
concrete abuse: an unauthenticated attacker can run
for i in {1..100000}; do curl -X POST https://<deployment>/api/ai/roast \
-H 'Content-Type: application/json' \
-d '{"mode":"roast","stats":{"commits":1,"languages":["ts"]}}'; done
each request calls gemini-2.5-flash and burns paid tokens. compare to /api/ai/weekly-summary (src/app/api/ai/weekly-summary/route.ts:152-197) which requires a session AND enforces last_ai_summary_at 24h window. same protection should apply here.
Proposed Fix
- add
getServerSession(authOptions) check, return 401 if no session
- resolve app user via
resolveAppUser and key rate limit by user.id
- add upstash fixed-window limiter (fallback to memory limiter) similar to /api/ai-insights, something like 5 requests / hour per user
- optionally cache the response by stats hash for a few minutes so refreshes are free
I would like to work on this under GSSoC 26. please assign!
for labels i think gssoc + level2 + type:security fits here.
Description
while reading through the ai/roast route i noticed it has no session check at all and no rate limiting, so anyone on the internet can hit it and spam gemini calls.
The Problem
src/app/api/ai/roast/route.ts:7-19:
POSThandler goes straight fromreq.json()intogenAI.getGenerativeModel(...)andmodel.generateContent(prompt). there is nogetServerSession, no bearer token check, no ip rate limit, no per-user quota.GEMINI_API_KEYis read at module load on line 5.concrete abuse: an unauthenticated attacker can run
each request calls gemini-2.5-flash and burns paid tokens. compare to /api/ai/weekly-summary (src/app/api/ai/weekly-summary/route.ts:152-197) which requires a session AND enforces
last_ai_summary_at24h window. same protection should apply here.Proposed Fix
getServerSession(authOptions)check, return 401 if no sessionresolveAppUserand key rate limit byuser.idI would like to work on this under GSSoC 26. please assign!
for labels i think gssoc + level2 + type:security fits here.