Description
POST /api/analytics/events accepts event tracking requests with no authentication and no rate limiting. Any client (or bot) can flood this endpoint with thousands of events per second, filling up the AnalyticsEvent table, degrading database performance, and skewing all metrics.
The userId field is taken from the x-user-id request header which is entirely client-controlled — any user can claim any other user's ID in analytics events.
More info
- Add IP-based rate limiting using a middleware solution (e.g.
@upstash/ratelimit with Upstash Redis, or a simple in-memory token bucket for development).
- For the
x-user-id header, replace the client-controlled header with a server-side session lookup: call auth() and use session?.user?.id instead of trusting the header.
- Consider batching analytics events on the client side (collect for 5s, then send a batch) to reduce request volume.
Description
POST /api/analytics/eventsaccepts event tracking requests with no authentication and no rate limiting. Any client (or bot) can flood this endpoint with thousands of events per second, filling up theAnalyticsEventtable, degrading database performance, and skewing all metrics.The
userIdfield is taken from thex-user-idrequest header which is entirely client-controlled — any user can claim any other user's ID in analytics events.More info
@upstash/ratelimitwith Upstash Redis, or a simple in-memory token bucket for development).x-user-idheader, replace the client-controlled header with a server-side session lookup: callauth()and usesession?.user?.idinstead of trusting the header.