Generation endpoints have no rate limiting / concurrency guard — shared links are an unlimited generation capability
Summary
app/api/get-next-completion-stream-promise/route.ts (~line 204) accepts any messageId, loads the chat, and calls together.chat.completions.stream with max_tokens: 20000 and a 270s deadline. There is no auth, no per-IP or per-chat throttle, no daily budget, and no check that a generation is already in flight for that message. /api/create-chat additionally runs a vision call per request, and /api/generate-chat-title runs an LLM call for any chatId. Public share URLs are /share/v2/<messageId>, so every shared link doubles as a valid generation capability for the underlying chat.
Impact
A simple loop can burn the Together balance in hours (each generation is up to 20k tokens / 4.5 min), fill the DB with junk chats, and eat Vercel function time. Nothing in the app surfaces it until the invoice.
Suggested fix
Add a limiter (e.g. @upstash/ratelimit) keyed by IP and by chatId in all three routes, return 429 when exceeded, and add a concurrency guard so one message can only have one in-flight generation:
const { success } = await ratelimit.limit(`gen:${ip}`)
if (!success) return new Response("Too many requests", { status: 429 })A daily global spend cap is a cheap extra safety net.
Context
Found by an automated full-codebase review (VibeAudit, Claude Fable 5.1). Full report: https://vibeaudit-amber.vercel.app/a/fx07llamacoder. Happy to be corrected if there's protection at the edge I can't see.
Source: Nutlope/llamacoder